Следующая команда при запуске в BASH очищает The Raven.
cat The_Raven.txt | gawk '{print tolower($0)}' | tr -d "\!\"#$%&'()*+,-./:;<=>?@[\\]^_\`{|}~"
Следующая команда изменяет The Raven, но делает файл нечитаемым.
cat The_Raven.txt | gawk '{print tolower($0)}' | tr -d "\!\"#$%&'()*+,-./:;<=>?@[\\]^_\`{|}~«»"
Следующий код Python использует subprocess
для очистки «Ворона».
command = "cat The_Raven.txt | gawk '{print tolower($0)}' | tr -d \"!\\\"#$%&'()*+,-./:;<=>?@[\\\\]^_\\`{|}~\""
cleaned_text_from_command = subprocess.run(command, shell = True, capture_output = True, text = True, encoding = 'utf-8').stdout
Вставка «»
после ~
в приведенный выше код Python приводит к следующей ошибке.
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 0-1: invalid continuation byte
Как удалить все соответствующие символы, включая «»
, если они присутствуют?
🤔 А знаете ли вы, что...
Python подходит для начинающих программистов благодаря своей простоте и читаемости кода.
Ваш файл начинается с UTF-8 BOM (ef bb bf
):
$ od -tx1 -N8 pg17192.txt
0000000 ef bb bf 54 68 65 20 50 0000010
Кодировка UTF-8 символа »
содержит байт (bb
) из спецификации:
$ echo '»' | od -tx1
0000000 c2 bb 0a
0000002
Следующий отрывок из man tr
предполагает, что многобайтовые символы могут не поддерживаться:
Полная поддержка доступна только для безопасных однобайтовых локалей, в которых каждый возможный входной байт представляет собой один символ.
И быстрый тест показывает, что это действительно так; tr -d
считает каждый байт символом и разбивает спецификацию (bb
отсутствует):
$ tr -d '»' <pg17192.txt | od -tx1 -N8
0000000 ef bf 54 68 65 20 50 72
0000010
Этого можно избежать, используя инструмент, поддерживающий многобайтовые символы:
$ sed 's/»//g' pg17192.txt | od -tx1 -N8
0000000 ef bb bf 54 68 65 20 50
0000010
Вы можете сделать это в Python с помощью чего-то вроде этого, отфильтровав из файла все небуквенно-цифровые символы и преобразуя их в нижний регистр.
#! /usr/bin/env python3
import itertools
with open("pg17192.txt") as file:
print(''.join((map(str.lower, filter(lambda c: c.isspace() or c.isalnum(), itertools.chain.from_iterable(l for l in file))))))
Некоторые наблюдения -
УУоК. gawk
вполне способен читать файл, не вызывая еще один процесс, у которого нет другой цели, кроме как передать данные на стандартный ввод. Используйте awk '{yourcode}' file
или даже awk '{yourcode}' < file
(операционная система прикрепит файл на стандартный ввод без cat
).
Точно так же awk
выполнит все эти подавления символов, не вызывая отдельный экземпляр tr
. Для такой небольшой работы это не имеет большого значения, но стоит выработать привычку отрезать ненужные фрагменты, когда вам предстоит более крупная работа, требующая большей эффективности. Практикуйтесь в малом, чтобы быть готовым к большому.
С другой стороны этого аргумента, если я не ошибаюсь, похоже, что вы просто убираете все знаки препинания. Если это правда, то для этого уже существует оптимизированный класс символов POSIX. Вероятно, вы сможете получить то, что хотите, с помощью
awk '{print tolower(gensub(/[[:punct:]]/,"","g")) }' The_Raven.txt
...но если вы уже работаете на Python, зачем вам раскошелиться на awk
?
import re
with open('The_Raven.txt', encoding = "utf-8" ) as file:
print( re.sub( '[^\s\w]', '', file.read() ) )