Nob*_*ift 2 xml character-encoding sed cygwin windows
我正在尝试使用 sed 和 cygwin 替换 Windows 上 20 多个文件中的 XML 元素。该行是:
cd "D:\Backups\Tasks"
sed -i 's~<StartWhenAvailable>true</StartWhenAvailable>~<StartWhenAvailable>false</StartWhenAvailable>~g' "Task_01.xml"
Run Code Online (Sandbox Code Playgroud)
这什么都代替不了。但是,如果我尝试:
sed 's~<~[~g' "Task_01.xml"
Run Code Online (Sandbox Code Playgroud)
它输出:
[AllowHardTerminate>true[/AllowHardTerminate>
[StartWhenAvailable>true[/StartWhenAvailable>
[RunOnlyIfNetworkAvailable>false[/RunOnlyIfNetworkAvailable>
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试只添加一个字符,它只会按原样输出文档:
sed 's~<B~[B~g' "Task_01.xml"
Run Code Online (Sandbox Code Playgroud)
以上没有任何作用。我究竟做错了什么?人字形是特殊字符还是我误用了 sed?或者是cygwin的错误?
Sté*_*las 10
最有可能的是,该文件是用 UTF-16 编码的,即每个字符有 2 或 4 个字节,甚至可能在开头带有字节顺序标记。
示例中显示的字符(所有 ASCII 字符)通常编码为 2 个字节,其中第一个或第二个字节(取决于它是 big-enfian 还是 little-endian UTF-16 编码)为 0,另一个为是 ASCII/Unicode 代码。0 字节通常在终端上是不可见的,因此当转储到那里时文本看起来没问题,因为其余的只是 ASCII,但实际上文本包含:
<[NUL]S[NUL]t[NUL]a[NUL]r[NUL]t[NUL]W[NUL]h[NUL]e[NUL]n[NUL]...
Run Code Online (Sandbox Code Playgroud)
您需要将该文本转换为您的语言环境的字符集sed
才能处理它。请注意,UTF-16 不能用作 Unix 语言环境中的字符编码。您不会找到使用 UTF-16 作为其字符编码的语言环境。
iconv -f utf-16 < Task_01.xml |
sed 's~<StartWhenAvailable>true</StartWhenAvailable>~<StartWhenAvailable>false</StartWhenAvailable>~g' |
iconv -t utf-16 > Task_01.xml.out
Run Code Online (Sandbox Code Playgroud)
假设输入有一个 BOM。如果不是,您需要确定它是大端还是小端(可能是小端)并将其更改utf-16
为utf-16le
或utf-16be
。
如果语言环境的字符集是 UTF-8,则即使文本包含非 ASCII 字符,也不应该在翻译中丢失任何内容。
由于 Cygwin 的sed
通常是 GNU sed
,因此它也可以自行处理该类型的二进制文件(因为它包含 NUL 字节),因此您还可以执行以下操作:
LC_ALL=C sed -i 's/t\x00r\x00u\x00e/f\x00a\x00l\x00s\x00e/g' Task_01.xml
Run Code Online (Sandbox Code Playgroud)
该file
命令应该能够告诉您输入是否确实是 UTF-16。您可以使用sed -n l
或od -tc
查看那些隐藏的 NUL 字符。带有 BOM 的 little-endian UTF-16 文本示例:
$ echo true | iconv -t utf-16 | od -tc
0000000 377 376 t \0 r \0 u \0 e \0 \n \0
0000014
$ echo true | iconv -t utf-16 | sed -n l
\377\376t\000r\000u\000e\000$
\000$
$ echo true | iconv -t utf-16 | file -
/dev/stdin: Little-endian UTF-16 Unicode text, with no line terminators
Run Code Online (Sandbox Code Playgroud)
为了处理与几个文件zsh
/ bash
/ ksh93
:
set -o pipefail
for file in ./*.xml; do
cp -ai "$file" "$file.bak" &&
iconv -f utf-16 < "$file.bak" |
sed 's~<StartWhenAvailable>true</StartWhenAvailable>~<StartWhenAvailable>false</StartWhenAvailable>~g' |
iconv -t utf-16 > "$file" &&
rm -f "$file.bak"
done
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1590 次 |
最近记录: |