如何从一个文件中删除所有非 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:]'