gpt4 book ai didi

bash - 如何将 ISO-8859-1 字符正确替换为 UTF-8?

转载 作者:行者123 更新时间:2023-12-02 02:39:17 27 4
gpt4 key购买 nike

我想替换下面文件中的 ISO-8859-1 字符以使其对 UTF-8 编码有效。

<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</HEAD>

<BODY>

<A NAME="top"></A>

<TABLE border=0 width=609 cellspacing=0 cellpadding=0>
<TR><td rowspan=2><img src="http://www.example.com" width=10></td>
<TD width=609 valign=top>

<p>'</p>
<p>*</p>
<p>-</p>
<p>—</p>
<p>§</p>
<p>«</p>
<p>»</p>
<p>¿</p>
<p>Á</p>

</TD>
</TR>
</TABLE>

</body>
</html>

通过一些研究,我发现问题与locale 语言有关,我能够构建这个 awk 程序,但只替换了前 2 个字符('*)

LC_ALL=ISO_8859-1 awk '{
gsub(/charset=iso-8859-1/, "charset=UTF-8" , $0)
gsub(/\047/, "\\&apos;" , $0)
gsub(/*/, "\\&ast;" , $0)
gsub(/–/, "\\&ndash;" , $0)
gsub(/—/, "\\&mdash;" , $0)
gsub(/§/, "\\&sect;" , $0)
gsub(/«/, "\\&laquo;" , $0)
gsub(/»/, "\\&raquo;" , $0)
gsub(/¿/, "\\&iquest;" , $0)
gsub(/Á/, "\\&Aacute;" , $0)
print
}' t.html | iconv -f ISO_8859-1 -t UTF-8

这是当前输出(下面显示部分输出,只有受程序影响的行):

<p>&apos;</p>
<p>&ast;</p>
<p>-</p>
<p>-</p>
<p>§</p>
<p>«</p>
<p>»</p>
<p>¿</p>
<p>Á</p>

预期的输出是:

<p>&ast;</p>
<p>&ndash;</p>
<p>&mdash;</p>
<p>&sect;</p>
<p>&laquo;</p>
<p>&raquo;</p>
<p>&iquest;</p>
<p>&Aacute;</p>

我已经使用 sed 尝试过类似的代码,但问题相同。

如何解决这个问题?

在语言环境配置下:

***Ubuntu 18.04.1 LTS

$ locale
LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_PAPER="C.UTF-8"
LC_NAME="C.UTF-8"
LC_ADDRESS="C.UTF-8"
LC_TELEPHONE="C.UTF-8"
LC_MEASUREMENT="C.UTF-8"
LC_IDENTIFICATION="C.UTF-8"
LC_ALL=

最佳答案

这个问题可能是由于输入文件和 awk 脚本之间的编码不匹配造成的。

请首先注意,ISO-8859-1 和 Windows-1252 之间可能存在(非常常见的)混淆。原始帖子中的 html 示例包含不属于 ISO-8859-1 layout 的 em/en 破折号字符, 所以它肯定使用了另一种编码,可能是 Windows-1252 (这是 ISO-8859-1 的超集,包括破折号字符)因为 OP 报告通过 Windows 子系统层使用 Ubuntu。

然后我会假设 html 输入文件确实是用 Windows-1252 编码的。所以非 ASCII 字符(代码点 ≥ 128)只使用一个字节。

如果 awk 程序是从以 UTF-8 编码的文件中加载的,或者甚至直接在使用 UTF-8 编码的终端窗口中键入,那么程序中嵌入的正则表达式和文字字符串也以 UTF 编码-8。所以非 ASCII 字符使用多个字节。

例如,字符 §(代码点 167 = 0xA7)在 Windows-1252 中由字节 A7 和字节序列 C2 表示UTF-8 格式的 A7。如果您在 UTF-8 编码的 awk 程序中使用 gsub(/§/, "S"),awk 会在输入文件中查找序列 C2 A7包含 A7。它不会匹配。除非你(不幸)足够幸运,在你的 § 之前有一个角色 Â(代码点 194 = 0xC2)。

更改区域设置在这里没有帮助,因为它只告诉 awk 如何解析其输入(数据和程序),而您在这里需要的是对数据或正则表达式进行转码。为此,您必须能够独立于程序的区域设置指定数据的区域设置,这是不受支持的。

因此,假设您的系统设置了 UTF-8 语言环境,并且您的 awk 脚本使用该语言环境(无论是从文件加载还是在终端中键入),您可以使用以下几种方法来对齐输入文件和相同编码的正则表达式,以便 gsub 按预期工作。

请注意,这些建议适用于您的第一个 awk 命令,因为它是问题的根源。仅当您有意不将输入中可能包含的所有特殊字符转换为 html 实体时,才需要最后一个到 iconv 的管道。否则 awk 的输出是纯 ASCII,因此已经符合 UTF-8 标准。

选项 1:将输入文件从 Windows-1252 转换为 UTF-8

在任何情况下都不需要另一个 iconv 步骤。

iconv -f WINDOWS-1252 t.html | awk '{
gsub(/charset=iso-8859-1/, "charset=UTF-8")
gsub(/\047/, "\\&apos;")
gsub(/\*/, "\\&ast;")
gsub(/–/, "\\&ndash;")
gsub(/—/, "\\&mdash;")
gsub(/§/, "\\&sect;")
gsub(/«/, "\\&laquo;")
gsub(/»/, "\\&raquo;")
gsub(/¿/, "\\&iquest;")
gsub(/Á/, "\\&Aacute;")
print
}'

选项 2:将 awk 程序从 UTF-8 转换为 Windows-1252

因为 awk 程序可能也想找点乐子。让我们使用进程替换。

awk -f <(iconv -t WINDOWS-1252 <<'EOS'
{
gsub(/charset=iso-8859-1/, "charset=UTF-8")
gsub(/'/, "\\&apos;")
gsub(/\*/, "\\&ast;")
gsub(/–/, "\\&ndash;")
gsub(/—/, "\\&mdash;")
gsub(/§/, "\\&sect;")
gsub(/«/, "\\&laquo;")
gsub(/»/, "\\&raquo;")
gsub(/¿/, "\\&iquest;")
gsub(/Á/, "\\&Aacute;")
print
}
EOS
) t.html

选项 3:将 awk/schell 脚本保存在以 Windows-1252 编码的文件中

...使用您最喜欢的工具。

选项 4:将终端 session 的编码切换为 Windows-1252

当然,如果您在终端中键入/粘贴 awk 命令。

请注意,这与设置语言环境 (LC_CTYPE) 不同。我不知道以编程方式执行此操作的方法。如果有人知道,请随意贡献。

选项 5:在 awk 程序中完全避免使用非 ASCII 字符

无论如何,在我看来这是一个很好的做法。

awk '{
gsub(/charset=iso-8859-1/, "charset=UTF-8")
gsub(/\047/, "\\&apos;")
gsub(/\*/, "\\&ast;")
gsub(/\226/, "\\&ndash;")
gsub(/\227/, "\\&mdash;")
gsub(/\247/, "\\&sect;")
gsub(/\253/, "\\&laquo;")
gsub(/\273/, "\\&raquo;")
gsub(/\277/, "\\&iquest;")
gsub(/\301/, "\\&Aacute;")
print
}' t.html

关于bash - 如何将 ISO-8859-1 字符正确替换为 UTF-8?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60796889/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com