Как удалить символы в списке?

Следующая команда при запуске в 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

Как удалить все соответствующие символы, включая «», если они присутствуют?

Не используйте encoding='utf-8', так как вывод не кодируется таким образом.

Barmar 17.06.2024 01:32

Кстати, я рекомендую использовать необработанную строку для command, чтобы не нужно было удваивать все обратные косые черты.

Barmar 17.06.2024 01:33

Почему вы делаете это с помощью подпроцесса? Все, что вы делаете с gawk и tr, можно легко сделать в самом Python.

Barmar 17.06.2024 01:34

Бармар, я пишу тест, который сравнивает очищенный текст из команды с очищенным текстом из функции, как меня просили.

Tom Lever 17.06.2024 01:57

Я удалил encoding = 'utf-8' по вашему предложению без изменений. Что касается изменения utf-8 на latin-1, latin-1 не может кодировать все символы в The Raven. Интересно, что команда BASH делает файл нечитаемым для Python.

Tom Lever 17.06.2024 02:22

Вы можете заменить tr ... на sed 's/[CHARLIST]//g' для поддержки UTF-8. Или вы можете использовать функции Python, чтобы сделать то же самое.

Wiimm 17.06.2024 10:43

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

user1934428 17.06.2024 11:39

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

Ed Morton 17.06.2024 12:30

Если вы просто пытаетесь преобразовать все символы в нижний регистр и удалить все символы пунктуации, это будет awk '{gsub(/[[:punct:]]/,""); print tolower($0)}' в любой POSIX awk. Если вы также хотите удалить управляющие символы, тогда gsub(/[[:punct:][:cntrl:]]/,""), а если вам действительно нужно удалить определенный список символов, тогда gsub(/[]!"#$%&\047()*+,./:;<=>?@[\\^_`{|}~-]/,"") или gsub(/[[:punct:]«»]/,"") и т. д. Что вам не нужно делать, так это перенаправлять вывод awk на tr.

Ed Morton 17.06.2024 12:51
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
10
142
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Ваш файл начинается с 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

Также стоит отметить, что tr -d '»' будет работать с реализацией tr BSD, поскольку он обрабатывает символы UTF-8 (как того требует POSIX). Я предполагаю, что вы тестируете здесь GNU tr, который не обрабатывает многобайтовые символы. Однако не уверен, как обстоят дела в других реализациях tr.

geirha 17.06.2024 12:18

Вы можете сделать это в 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() ) )

Другие вопросы по теме