- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想替换下面文件中的 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/, "\\'" , $0)
gsub(/*/, "\\*" , $0)
gsub(/–/, "\\–" , $0)
gsub(/—/, "\\—" , $0)
gsub(/§/, "\\§" , $0)
gsub(/«/, "\\«" , $0)
gsub(/»/, "\\»" , $0)
gsub(/¿/, "\\¿" , $0)
gsub(/Á/, "\\Á" , $0)
print
}' t.html | iconv -f ISO_8859-1 -t UTF-8
这是当前输出(下面显示部分输出,只有受程序影响的行):
<p>'</p>
<p>*</p>
<p>-</p>
<p>-</p>
<p>§</p>
<p>«</p>
<p>»</p>
<p>¿</p>
<p>Á</p>
预期的输出是:
<p>*</p>
<p>–</p>
<p>—</p>
<p>§</p>
<p>«</p>
<p>»</p>
<p>¿</p>
<p>Á</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 标准。
在任何情况下都不需要另一个 iconv
步骤。
iconv -f WINDOWS-1252 t.html | awk '{
gsub(/charset=iso-8859-1/, "charset=UTF-8")
gsub(/\047/, "\\'")
gsub(/\*/, "\\*")
gsub(/–/, "\\–")
gsub(/—/, "\\—")
gsub(/§/, "\\§")
gsub(/«/, "\\«")
gsub(/»/, "\\»")
gsub(/¿/, "\\¿")
gsub(/Á/, "\\Á")
print
}'
因为 awk 程序可能也想找点乐子。让我们使用进程替换。
awk -f <(iconv -t WINDOWS-1252 <<'EOS'
{
gsub(/charset=iso-8859-1/, "charset=UTF-8")
gsub(/'/, "\\'")
gsub(/\*/, "\\*")
gsub(/–/, "\\–")
gsub(/—/, "\\—")
gsub(/§/, "\\§")
gsub(/«/, "\\«")
gsub(/»/, "\\»")
gsub(/¿/, "\\¿")
gsub(/Á/, "\\Á")
print
}
EOS
) t.html
...使用您最喜欢的工具。
当然,如果您在终端中键入/粘贴 awk 命令。
请注意,这与设置语言环境 (LC_CTYPE) 不同。我不知道以编程方式执行此操作的方法。如果有人知道,请随意贡献。
无论如何,在我看来这是一个很好的做法。
awk '{
gsub(/charset=iso-8859-1/, "charset=UTF-8")
gsub(/\047/, "\\'")
gsub(/\*/, "\\*")
gsub(/\226/, "\\–")
gsub(/\227/, "\\—")
gsub(/\247/, "\\§")
gsub(/\253/, "\\«")
gsub(/\273/, "\\»")
gsub(/\277/, "\\¿")
gsub(/\301/, "\\Á")
print
}' t.html
关于bash - 如何将 ISO-8859-1 字符正确替换为 UTF-8?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60796889/
我是一名优秀的程序员,十分优秀!