escape-символы регулярного выражения Python - PullRequest
2 голосов
/ 02 декабря 2009

У нас есть:

>>> str
'exit\r\ndrwxr-xr-x    2 root     root            0 Jan  1  2000 
\x1b[1;34mbin\x1b[0m\r\ndrwxr-xr-x    3 root     root           
0 Jan  1  2000 \x1b[1;34mlib\x1b[0m\r\ndrwxr-xr-x   10 root     
root            0 Jan  1  1970 \x1b[1;34mlocal\x1b[0m\r\ndrwxr-xr-x    
2 root     root            0 Jan  1  2000 \x1b[1;34msbin\x1b[0m\r\ndrwxr-xr-x    
5 root     root            0 Jan  1  2000 \x1b[1;34mshare\x1b[0m\r\n# exit\r\n'

>>> print str
exit
drwxr-xr-x    2 root     root            0 Jan  1  2000 bin
drwxr-xr-x    3 root     root            0 Jan  1  2000 lib
drwxr-xr-x   10 root     root            0 Jan  1  1970 local
drwxr-xr-x    2 root     root            0 Jan  1  2000 sbin
drwxr-xr-x    5 root     root            0 Jan  1  2000 share
# exit

Я хочу избавиться от всей ерунды '\ xblah [0m' 'с помощью регулярных выражений. Я пробовал

re.sub(str, r'(\x.*m)', '')

Но это не помогло. Есть идеи?

Ответы [ 5 ]

11 голосов
/ 02 декабря 2009

У вас есть несколько вопросов:

  • Вы передаете аргументы re.sub в неправильном порядке. Должно быть:

    re.sub (regexp_pattern, замена, source_string)

  • Строка не содержит "\ x". Этот \ x1b является escape-символом, и это один символ.

  • Как указал междурядный, вы хотите ". *?" вместо ". *", потому что в противном случае он будет соответствовать всему от первого побега до последнего "m".

Правильный вызов re.sub:

print re.sub('\x1b.*?m', '', s)

В качестве альтернативы вы можете использовать:

print re.sub('\x1b[^m]*m', '', s)
3 голосов
/ 02 декабря 2009

Это Коды терминала ANSI . Они сигнализируются ESC (байт 27, видимый в Python как \x1B), за которым следует [, затем некоторые ; -разделенные параметры и, наконец, буква, указывающая, какая это команда. (m - это изменение цвета.)

Параметры обычно являются числами, поэтому для этого простого случая вы можете избавиться от них с помощью:

ansisequence= re.compile(r'\x1B\[[^A-Za-z]*[A-Za-z]')
ansisequence.sub('', string)

Технически для некоторых (не связанных с цветом) управляющих кодов они могут быть общими строками, что делает синтаксический анализ раздражающим. Это редко встречается, но если бы вы это сделали, я думаю, вам пришлось бы использовать что-то сложное, например:

\x1B\[((\d+|"[^"]*")(;(\d+|"[^"]*"))*)?[A-Za-z]

Лучше всего было бы убедить всех, кто генерирует строку, что вы не являетесь терминалом ANSI, поэтому он не должен включать цветовые коды в свой вывод.

3 голосов
/ 02 декабря 2009

Вам необходимы следующие изменения:

  • Избежать обратной косой черты
  • Переключиться на сопоставление без жадности. В противном случае все, что находится между первым \x и последним m, будет удалено, что будет проблемой при наличии более одного вхождения.
  • Порядок аргументов неверен

Результат:

re.sub(r'(\\x.*?m)', '', str)
2 голосов
/ 02 декабря 2009

Попробуйте вместо этого запустить ls --color=never -l, и вы не получите коды выхода ANSI.

1 голос
/ 02 декабря 2009

Вот пример решения вашей проблемы с общим синтаксическим выражением для этих надоедливых escape-последовательностей. Преобразование исходной строки с подавленным выражением возвращает строку, очищенную от всех совпадений выражения.

s = \
'exit\r\ndrwxr-xr-x    2 root     root            0 Jan  1  2000 ' \
'\x1b[1;34mbin\x1b[0m\r\ndrwxr-xr-x    3 root     root           ' \
'0 Jan  1  2000 \x1b[1;34mlib\x1b[0m\r\ndrwxr-xr-x   10 root     ' \
'root            0 Jan  1  1970 \x1b[1;34mlocal\x1b[0m\r\ndrwxr-xr-x    ' \
'2 root     root            0 Jan  1  2000 \x1b[1;34msbin\x1b[0m\r\ndrwxr-xr-x    ' \
'5 root     root            0 Jan  1  2000 \x1b[1;34mshare\x1b[0m\r\n# exit\r\n' \

from pyparsing import (Literal, Word, nums, Combine, 
    delimitedList, oneOf, alphas, Suppress)

ESC = Literal('\x1b')
integer = Word(nums)
escapeSeq = Combine(ESC + '[' + delimitedList(integer,';') + oneOf(list(alphas)))

s_prime = Suppress(escapeSeq).transformString(s)

print s_prime

Это печатает желаемый вывод, сохраненный в s_prime.

...