Преобразовать многострочную строку, напечатанную как строковый тип, в правильную строку - PullRequest
0 голосов
/ 29 мая 2019

В моих файлах журналов есть несколько многострочных байтов, например

[2019-05-25 19:16:31] b'logstring \ r \ n \ r \ nmore log '

После того, как я попытаюсь извлечь исходную многострочную строку, как мне преобразовать ее в реальную строку, используя Python 3?

В качестве упрощенного примера, после прочтения файла журнала и сокращения времени, я получаюпеременная с типом str и префиксом b 'в виде строки.

# note: b'' is inside the str (taken from log)
tmp =  "b'logstring\r\n\r\nmore log'"
# convert here  
print(tmp)

Я ищу способ сообщить Python, что контент должен быть декодирован.Но str не разрешает декодирование.

Результат, который я хотел бы видеть из команды печати:

logstring
more log

ОБНОВЛЕНИЕ: функция "eval" выдаст этот результат, но этовыполнит код, так что это небезопасно.

# note: b'' is inside the str (taken from log)
tmp =  "b'logstring\r\n\r\nmore log'"
tmp = eval(tmp) 
print(tmp)

Есть ли лучший способ?

Ответы [ 3 ]

1 голос
/ 29 мая 2019

Вы можете использовать регулярное выражение:

import re
tmp =  "b'logstring\r\n\r\nmore log'"
r = re.compile(r"b'(.+)'", re.DOTALL|re.MULTILINE)
result = r.sub(r"\1", tmp)
print(result) # logstring\r\n\r\nmore log

Вы можете использовать это для всего файла или построчно, но вам может потребоваться немного изменить этот код в соответствии с вашими потребностями.

- Правка -
Если вы хотите удалить дубликаты новой строки (как показывает желаемый результат), вы можете сделать это следующим образом:

import re
tmp =  "b'logstring\r\n\r\nmore log'"
binary_regex = re.compile(r"b'(.+)'", re.DOTALL|re.MULTILINE)
newline_regex = re.compile(r"(\r\n)+", re.DOTALL|re.MULTILINE)
# Make sure to do the compiles outside of any loops you have
result = binary_regex.sub(r"\1", tmp) # Remove the b''
result = newline_regex.sub(r"\r\n", result) # Remove duplicate new lines
print(result)

Выход:

logstring
more log
0 голосов
/ 30 мая 2019

Кажется, что вы можете заблокировать функцию eval, чтобы она не могла запускать функции и встроенные функции python. Вы делаете это, передавая словарь разрешенных глобальных и локальных функций. Отобразив все встроенные функции в None, вы можете заблокировать выполнение обычных команд Python. Имея это в виду, использование eval для оценки содержимого строки безопасно.

Источник эта статья

# note: b'' is inside the str (taken from log)
tmp =  "b'logstring\r\n\r\nmore log'"
tmp = eval(tmp, {'__builtins__': None}, {}) 
print(tmp)

И в комментариях выше @juanpa.arrivillaga предложил другое решение, которое также решает проблему безопасности eval:

import ast

tmp =  "b'logstring\r\n\r\nmore log'"
tmp = ast.literal_eval(tmp) 
print(tmp)
0 голосов
/ 29 мая 2019
tmp =  "b'logstring\r\n\r\n\r\nmore log'"
tmp = tmp[2:-1]
start_pos = tmp.find('\r')
end_pos =start_pos
for x  in range (start_pos,len(tmp),2):
    if tmp[x:x+1] == '\r' or tmp[x:x+1] == '\n':
        end_pos +=2
if start_pos !=end_pos:
    tmp = tmp[:start_pos] + '\r\n' + tmp[end_pos:]
print(tmp)

вывод:

logstring
more log
...