Как можно очистить строку, чтобы она содержала только печатные символы ASCII? - PullRequest
0 голосов
/ 29 июня 2019

Мне нужна функция, которая будет очищать строку. Строка, возвращаемая дезинфицирующим средством, должна содержать только то, что будет символом от ASCII # 32 (символ пробела) до ASCII # 126 ('~').

Символ ASCII # 9 (символ табуляции) должен быть заменен четырьмя пробелами. Все остальные недопустимые символы должны быть заменены пустыми строками. Например, «\ n» будет заменено пустой строкой. Мы не хотим, чтобы недопустимые символы заменялись строками, представляющими соответствующие escape-последовательности. Например, мы не хотим, чтобы символ новой строки был заменен символом обратной косой черты и символом 'n'.

Хорошо, если последняя строка кодируется в Юникоде, а не в ASCII. Я просто хочу, чтобы единственные разрешенные символы были следующими:

" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"

ПРИМЕР ИСПОЛЬЗОВАНИЯ:

unsafe_string = "\u2502\u251cAPPLES\n\t\t\t\t\t\r\r AND \n\nBANANAS"
safe_string = sanitize(unsafe_string)
print(safe_string)

ВЫХОД:

APPLES                     AND BANANAS   

EDIT:

Следующие попытки решения не работают, поскольку они не могут отфильтровать символы новой строки.

import string
import re

unsafe_string = "\u2502\u251cAPPLES\n\t\t\t\t\t\r\r AND \n\nBANANAS"

safe_string = re.sub(r'[^\x00-\x7f]',r'', unsafe_string) 
print(safe_string)    

printable = set(string.printable)
safe_string = ''.join(filter(lambda x: x in printable, unsafe_string))
print(safe_string)

Ответы [ 2 ]

3 голосов
/ 29 июня 2019
import re

def sanitize(s):
    s = s.replace("\t", "    ")
    return re.sub(r"[^ -~]", "", s)

[ -~] означает «все в диапазоне от (пробел) до ~».Добавление ^ в начале означает все, кроме этого.

Вывод:

APPLES                     AND BANANAS

В вашем примере вывода вы забыли заменить табуляцию пробелами.

0 голосов
/ 29 июня 2019

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

def sanitize(unsafe_str): 
    allowed_range = set(range(32, 127)) 
    safe_str = '' 
    for char in unsafe_str: 
        cp = ord(char) 
        if cp in allowed_range: 
            safe_str += char 
        elif cp == 9: 
            safe_str += ' ' * 4 
    return re.sub(r'\s+', ' ', safe_str) 

Пример:

In [1042]: unsafe_string = "\u2502\u251cAPPLES\n\t\t\t\t\t\r\r AND \n\nBANANAS"                                                                                                                             

In [1043]: def sanitize(unsafe_str): 
      ...:     allowed_range = set(range(32, 127)) 
      ...:     safe_str = '' 
      ...:     for char in unsafe_str: 
      ...:         cp = ord(char) 
      ...:         if cp in allowed_range: 
      ...:             safe_str += char 
      ...:         elif cp == 9: 
      ...:             safe_str += ' ' * 4 
      ...:     return re.sub(r'\s+', ' ', safe_str) 
      ...:      
      ...:                                                                                                                                                                                                  

In [1044]: sanitize(unsafe_string)                                                                                                                                                                          
Out[1044]: 'APPLES AND BANANAS'

Последний re.sub(r'\s+', ' ', safe_str)кусок состоит в том, чтобы сжать пробелы в один.Если вы не хотите, чтобы это делали только return safe_str:

In [1046]: def sanitize(unsafe_str): 
      ...:     allowed_range = set(range(32, 127)) 
      ...:     safe_str = '' 
      ...:     for char in unsafe_str: 
      ...:         cp = ord(char) 
      ...:         if cp in allowed_range: 
      ...:             safe_str += char 
      ...:         elif cp == 9: 
      ...:             safe_str += ' ' * 4 
      ...:     return safe_str 
      ...:                                                                                                                                                                                                     

In [1047]: sanitize(unsafe_string)                                                                                                                                                                          
Out[1047]: 'APPLES                     AND BANANAS'

FWIW, это генерирует список разрешенных при каждом запуске функции, но поскольку это константа, вы можете поместить ее вуровень модуля, чтобы он генерировался только один раз, например:

ALLOWED_RANGE = set(range(32, 127)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...