Применение управляющих символов к строке — Python

Я пытаюсь применить управляющие символы, такие как '\x08 \x08', которые должны удалить прецедентный символ, к строке (переместиться назад, записать пробел, переместиться назад)
Например, когда я набираю в консоли python:

s = "test\x08 \x08"
print s
print repr(s)

Я захожу в свой терминал :

tes
'test\x08 \x08'

Я ищу функцию, скажем, «функцию», которая будет «применять» управляющие символы к моей строке:

v = function("test\x08 \x08")
sys.stdout.write(v)
sys.stdout.write(repr(v))

поэтому я получаю "чистую" строку без управляющих символов:

tes
tes

Я понимаю, что в терминале эта часть обрабатывается клиентом, поэтому, возможно, есть способ получить отображаемую строку, используя основные функции Unix.

echo -e 'test\x08 \x08'
cat file.out # control char are here handled by the client
>> tes
cat -v file.out # which prints the "actual" content of the file
>> test^H ^H

person Perceval W    schedule 12.04.2016    source источник
comment
Вы можете обработать backspace как '\r' (т. е. возврат каретки), а затем написать предыдущую строку, но я думаю, это будет неудобно.   -  person Wayne Werner    schedule 12.04.2016
comment
Управляющие символы зависят от типа терминала, они хранятся либо в базе данных terminfo, либо в базе данных termcap. Таким образом, python должен будет использовать эти базы данных для перевода \x08 во все, что вы думаете, что это означает для вашего конкретного типа терминала. Если вы используете только небольшое количество этих символов, вы можете понять это самостоятельно. Откуда берутся эти данные? См. также docs.python.org/3/library/termios.html# модуль-termios   -  person cdarke    schedule 12.04.2016


Ответы (1)


На самом деле ответ был немного сложнее простого форматирования.

Каждый символ, отправленный процессом на терминал, можно рассматривать как переход в конечном автомате (FSM). Состояние этого FSM примерно соответствует отображаемому предложению и положению курсора, но есть много других переменных, таких как размеры терминала, текущая вводимая последовательность управления *, режим терминала (например, режим VI / классическая консоль BASH), и т.п.

Хорошую реализацию этого FSM можно увидеть в исходном коде pexpect. .

Чтобы ответить на мой вопрос, не существует базовой «функции» Unix, которая может форматировать строку в соответствии с тем, что отображается в терминале, поскольку такая функция специфична для терминала, который отображает вывод процесса, и вы бы придется переписать полный терминал, чтобы обрабатывать все возможные символы и управляющие последовательности.

Однако мы можем реализовать простой пример сами. Нам нужно определить FSM с начальным состоянием:

  • отображаемая строка: "" (пустая строка)
  • положение курсора: 0

и переходы (ввод символов):

  • любой буквенно-цифровой символ/символ пробела: заменяет символ в позиции курсора на себя (или добавляет, если его нет) и увеличивает позицию курсора
  • \x08 шестнадцатеричный код: уменьшает позицию курсора

и подайте ему строку.

Python-решение

def decode(input_string):

    # Initial state
    # String is stored as a list because
    # python forbids the modification of
    # a string
    displayed_string = [] 
    cursor_position = 0

    # Loop on our input (transitions sequence)
    for character in input_string:

        # Alphanumeric transition
        if str.isalnum(character) or str.isspace(character):
            # Add the character to the string
            displayed_string[cursor_position:cursor_position+1] = character 
            # Move the cursor forward
            cursor_position += 1

        # Backward transition
        elif character == "\x08":
            # Move the cursor backward
            cursor_position -= 1
        else:
            print("{} is not handled by this function".format(repr(character)))

    # We transform our "list" string back to a real string
    return "".join(displayed_string)

И пример

>>> decode("test\x08 \x08")
tes 

Примечание о последовательностях управления

Управляющая последовательность ANSI представляет собой набор символов, которые действуют как переход в состояние (отображение/курсор/режим терминала/...) терминала. Это можно рассматривать как уточнение нашего состояния FSM и переходов с большим количеством подсостояний и подпереходов.

Например: когда вы нажимаете клавишу UP в классическом терминале Unix (например, VT100), вы фактически вводите управляющую последовательность: ESC 0 A, где ESC — шестнадцатеричный код \x1b. ESC переходит в режим ESCAPE и возвращается в нормальный режим после A.

Некоторые процессы интерпретируют эту последовательность как перемещение вертикальной позиции курсора (VI), другие — как движение назад по истории (BASH): это полностью зависит от программы, которая обрабатывает ввод.

Тем не менее, та же самая последовательность может использоваться для процесса вывода, но она, скорее всего, будет перемещать курсор вверх по экрану: это зависит от реализации терминала.

Хороший список управляющих последовательностей ANSI доступен здесь.

person Perceval W    schedule 28.04.2017
comment
Спасибо за столь подробный ответ на собственный вопрос. Помог мне! - person curious_weather; 28.09.2017