从工作流程(文件)中删除所有非 ASCII 字符

从工作流程(文件)中删除所有非 ASCII 字符

如何从一个文件中删除所有非 ASCII 字符?是否有特定的命令来执行此操作?

grep --colour='auto' -P -n'[^\x00-\x7]' /usr/local/...

我相信这会找到工作流程中的字符,但是我如何删除相关字符的所有实例?

答案1

ASCII 字符是0 到 177(八进制)范围内的字符(含 0 和 177)

要删除文件中超出此范围的字符,请使用

LC_ALL=C tr -dc '\0-\177' <file >newfile

tr命令是一个适用于单个字符的实用程序,或者用其他单个字符(音译)替换它们,删除它们,或者将相同字符的运行压缩为单个字符。

上面的命令将从 读取file修改的内容并将其写入到newfile.该-d选项tr使实用程序删除字符(而不是音译它们),并-c使其考虑给定间隔之外(而不是内部)的字符。

LC_ALL=C确保每个字节值都构成有效字符。如果没有它,某些tr实现如果发现在区域设置的字符编码中不形成有效字符的字节序列,就会中止。


要将原始文件替换为修改后的文件,请使用

LC_ALL=C tr -dc '\0-\177' <file >newfile &&
mv newfile file

tr成功完成后,这会将新文件重命名为旧文件的名称。如果tr未成功完成,可能是因为无法读取原始文件或无法写入新文件,则原始文件将保持不变。

或者,要尽可能多地保留原始文件的元数据(权限等),请使用

cp file tmpfile &&
LC_ALL=C tr -dc '\0-\177' <tmpfile >file &&
rm tmpfile

答案2

perl

perl -pi -e 's/[^[:ascii:]]//g'

答案3

如果您需要的只是一个正则表达式:[\x00-\x7F].
您可以将其应用于多个实用程序:

<file LC_ALL=C   sed   's/[^\o0-\o177]//g'      # GNU sed not POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^\0-\177]/,"");print}'
<file            perl  -pe 's/[^[:ascii:]]//g;'
<file            tr    -dc '\0-\177'

了解 sed、awk 和 perl 需要 Unix 中定义的“文本文件”。在这种情况下一切正常。但具体来说,awk 添加了一个尾随新行(无论它是否存在于源文件中)(用 printf 替换 print 可以删除输入中的所有换行符)。该tr文件旨在处理任何文件类型。然而,NUL ( \0) 不是 a 中的有效字符POSIX 文本文件并且应该避免:

这些行不包含 NUL 字符...

事实上,许多控制字符在某些特定条件下会产生其他问题。
所以,可能你需要[\x07-\x0d\x20-\x7e]

<file LC_ALL=C   sed   's/[^\o007-\o015\o040-\o176]//g'            # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^\0-\15\40-\176]/,"");print}'
<file            perl  -pe 's/[^\x{7}-\x{d}\x{20}-\x{7e}]//g;'
<file            tr    -dc '\7-\15\40-\176'

范围 7-13(十进制)是\a\b\t\n\v\f\r(按顺序)。
类似的(可能更便携)范围可以写成[^[:space:][:print:]] (similar because it doesn't include\a\b` --bell and backspace--)。

<file LC_ALL=C   sed   's/[^[:space:][:print:]]//g'  # GNU sed without POSIXLY_CORRECT
<file LC_ALL=C   awk   '{gsub(/[^[:space:][:print:]]/,"");print}'
<file            perl   -pe 's/[^[:space:][:print:]]//g;'
<file            tr     -dc '[:space:][:print:]'

有关的:
正则表达式任何 ASCII 字符
Perl解决方案
Posix 文本文件

相关内容