sed(和其他工具)会破坏非ASCII文件吗?

3
如果我编写一些脚本来操作文件,比如使用sed进行搜索/替换,而这些文件可能存在于各种字符集中,那么这些文件会被损坏吗?
我希望替换的文本是ASCII码,并且仅出现在只包含ASCII字符的文件行中,但文件的其余行包含其他字符集中的字符。

我的回答是针对你唯一的问题。然而,其他字符集可能也可以使用。由于你在这里还没有收到任何答案,所以最好的选择是在其他地方搜索。 - KevinDTimm
1
你可以轻松地通过将一些文件复制到临时目录中,使用sed进行修改,然后查看这些文件是否会使使用它们的程序崩溃来测试它。祝你好运。 - shellter
1
好的,这些文件太多了,太大了,无法彻底测试。希望能得到专家意见。 :) - user1264579
“diff”命令能否告诉我文件中是否有非ASCII内容被更改了(逐行基础上)?-a开关能处理非ASCII字符集吗? - user1264579
这些事情没有得到很好的标准化,因此一般的答案是这将取决于您的平台。实际上,Linux在处理8位数据方面比BSD更加强大。 - tripleee
此外,Perl 可能比 sed 更加强大。在 Perl 发行版中有一个名为 s2p 的脚本,可以将 sed 转换为 Perl,但简单的搜索和替换脚本基本上是相同的。 - tripleee
1个回答

5
如果你的字符集是单字节编码(如ISO-8859-n系列)或UTF-8,其中换行符与ASCII相同,且NUL字符(\0)不会出现,那么你的操作很可能可以运行。如果文件使用UTF-16,则无法运行(因为存在NUL字符)。为什么对于简单的ASCII字符串搜索和替换可以正常工作的原因是:我们假设你的编码是ASCII的超集,在这种简单匹配的情况下,sed将在字节级别上执行大部分操作,并只需用另一个字节序列替换一个字节序列。
但是:对于更复杂的操作,例如当您要替换的字符串或替换字符串包含特殊字符时,结果可能会有所不同。例如,您在命令行中输入的重音字符可能与您的文件编码不匹配,如果控制台编码/区域设置与文件编码不同。可以绕过这个问题,但需要小心。 sed中的某些操作取决于您的区域设置,例如哪些字符被认为是字母数字字符。例如,在使用波兰语UTF-8区域设置和使用ASCII的C区域设置中执行以下替换的比较:
$ echo "gęś gęgała" | LC_ALL=pl_PL.UTF-8 sed -e 's/[[:alnum:]]/X/g'
XXX XXXXXX
$ echo "gęś gęgała" | LC_ALL=C sed -e 's/[[:alnum:]]/X/g'
Xęś XęXXłX

但是如果您只想替换文字字符串,它会按预期工作:

$ echo "gęś gęgała" | LC_ALL=pl_PL.UTF-8 sed -e 's/g/G/g'
Gęś GęGała
$ echo "gęś gęgała" | LC_ALL=C sed -e 's/g/G/g'
Gęś GęGała

正如你所看到的,结果不同是因为根据语言环境,重音字符的处理方式不同。简而言之:字面ASCII字符串的替换很可能可以正常工作,更复杂的操作需要仔细研究,可能会起作用,也可能不会。


+100 感谢您帮助一个陌生人所付出的解释和努力。因此,更改环境语言/字符集以匹配每个目标文件似乎会有所帮助。### 此外,我的搜索/替换仅针对仅包含 ASCII 字符的行中的 ASCII 字符-如果我正确理解,那么包含其他字符的行只会在字符集可能混淆换行符的情况下造成潜在问题? - user1264579
@user1264579 是的。如果您只是将文本字符串替换为其他文本字符串,那么换行符只需与 ASCII 中的相同,而 NUL 则不需要出现才能使替换正常工作。ASCII 以外的字符也应该没问题。当然,即使替换在字节上是正确的,您也需要确保它在目标编码中的含义是您想要的。如果您在使用 Latin-2 的文件中正确替换了以 UTF-8 编码的 ę,则替换将正确插入表示 ę 的 2 个字节,但这些字节将与文件的其余部分一起在 Latin-2 中显示为垃圾。 - Michał Kosmulski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接