以下命令在 BASH 中运行时将清理

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

我如何删除所有相关字符(包括«»存在的字符)?

11

  • 2
    不要使用encoding='utf-8',因为输出不是像那样编码的。


    – 

  • 2
    顺便说一句,我建议您使用原始字符串command,这样您就不需要将所有反斜杠加倍。


    – 

  • 1
    改成utf-8latin-1


    – 

  • 4
    为什么要使用 subprocess 来执行此操作?您所做的一切都gawk可以tr在 python 本身中轻松完成。


    – 


  • Barmar,我正在编写一个测试,按照我的要求将命令中清理的文本与函数中清理的文本进行比较。


    – 



最佳答案
3

您的文件以 UTF-8 开头( ef bb bf):

$ od -tx1 -N8 pg17192.txt
0000000 ef bb bf 54 68 65 20 50                                 0000010

字符的 UTF-8 编码包含来自 BOM 的»字节 ( ):bb

$ echo '»' | od -tx1
0000000 c2 bb 0a
0000002

以下摘录man tr表明可能不支持多字节字符:

仅对安全的单字节区域设置才提供完全支持,其中每个可能的输入字节代表一个字符。

快速测试表明情况确实如此;tr -d将每个字节视为一个字符并破坏 BOM(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

1

  • 还值得注意的是,它将tr -d '»'与 BSD 的实现兼容tr,因为它处理 UTF-8 字符(POSIX 要求)。我猜你tr在这里测试的是 GNU,它不处理多字节字符。tr但不确定其他实现如何。


    – 


您可以在 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完全能够读取文件,而无需调用另一个除了将数据输入到 stdin 上之外没有其他目的的进程。使用awk '{yourcode}' file或 甚至awk '{yourcode}' < file(操作系统会在没有 的情况下 cat将文件附加到 stdin 上)。

同样的道理,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() ) )