LC_ALL=C 是否应该始终用于非区域设置特定的 sed 操作?
Should LC_ALL=C Always be used for Non-Locale-Specific sed Operations?
我有 JSON 个文件,这些文件带有我在使用 jq
进行操作之前删除的注释。我刚刚遇到了一个有趣的问题,我收到了一个 JSON 文件,其中包含一些富文本引号字符(十六进制 93 和十六进制 94)的注释注释。我现有的 sed 点 .
字符与这些字符不匹配。这是一个演示:
首先输入:
% echo -e '# \x93text\x94\n{"a":1}' | od -c
0000000 # 223 t e x t 224 \n { " a " : 1 }
0000020 \n
0000021
%
这是转换:
% echo -e '# \x93text\x94\n{"a":1}' | sed 's/^\s*#.*//' | od -c
0000000 223 t e x t 224 \n { " a " : 1 } \n
0000017
%
请注意,sed 表达式中的点字符与十六进制 93 字符不匹配。但是,如果我包括 LC_ALL=C
:
% echo -e '# \x93text\x94\n{"a":1}' | LC_ALL=C sed 's/^\s*#.*//' | od -c
0000000 \n { " a " : 1 } \n
0000011
%
然后 sed 表达式中的点字符匹配十六进制 93 和十六进制 94 字符。 sed 文档部分 Locale Considerations 谈到括号表达式,但上面的行为似乎证明这个问题发生在其他地方。
有趣的是,删除而不是替换并没有显示这个问题:
% echo -e '# \x93text\x94\n{"a":1}' | sed '/^\s*#.*/d' | od -c
0000000 { " a " : 1 } \n
0000010
鉴于我操作的是带注释的 JSON 文件,我认为在 sed 语句中添加 LC_ALL=C
的解决方案是合理的。
所以,我的问题是: 正在使用 LC_ALL=C
我在进行非语言环境特定的 sed
转换时一直想使用的东西(就像适用于带注释的 JSON 文件)?如果没有,有什么替代方法可以避免我上面显示的问题?
我的环境:
- CentOS 7.3 [kernel-3.10.0-514.6.1.el7.x86_64]
- sed(GNU sed)4.2.2 [sed-4.2.2-5.el7.x86_64]
- Bash 4.2.46(1) [bash-4.2.46-21.el7_3.x86_64]
C 语言环境是一种特殊的语言环境,旨在成为最简单的语言环境。您也可以说,虽然其他语言环境适用于人类,但 C 语言环境适用于计算机。 在 C 语言环境中,字符是单字节,字符集是 ASCII
在某些系统上,POSIX 语言环境存在差异,例如 non-ASCII 个字符的排序顺序未定义。
所以 LC_ALL=C 是将非第 8 位字符考虑在内的安全方法。
查看比较
使用 LC,sed 算作字符的一部分
echo -e '# \x93text\x94\n{"a":1}' | LC_ALL=C sed 's/[^[:alnum:]]/[HERE:&] /g' | od -c
0000000 [ H E R E : # ] [ H E R E :
0000020 ] [ H E R E : 223 ] t e x t [
0000040 H E R E : 224 ] \n [ H E R E : {
0000060 ] [ H E R E : " ] a [ H E R
0000100 E : " ] [ H E R E : : ] 1 [
0000120 H E R E : } ] \n
没有 LC,sed 不计入要考虑的字符的一部分([[:alnum:]]
和 [^[:alnum:]]
不要 参见 第 8 位字符)
echo -e '# \x93text\x94\n{"a":1}' | sed 's/[[:alnum:]]/[HERE:&] /g' | od -c
0000000 # 223 [ H E R E : t ] [ H E R
0000020 E : e ] [ H E R E : x ] [ H
0000040 E R E : t ] 224 \n { " [ H E R E
0000060 : a ] " : [ H E R E : 1 ] }
0000100 \n
echo -e '# \x93text\x94\n{"a":1}' | sed 's/[^[:alnum:]]/[HERE:&] /g' | od -c
0000000 [ H E R E : # ] [ H E R E :
0000020 ] 223 t e x t 224 \n [ H E R E : {
0000040 ] [ H E R E : " ] a [ H E R
0000060 E : " ] [ H E R E : : ] 1 [
0000100 H E R E : } ] \n
我有 JSON 个文件,这些文件带有我在使用 jq
进行操作之前删除的注释。我刚刚遇到了一个有趣的问题,我收到了一个 JSON 文件,其中包含一些富文本引号字符(十六进制 93 和十六进制 94)的注释注释。我现有的 sed 点 .
字符与这些字符不匹配。这是一个演示:
首先输入:
% echo -e '# \x93text\x94\n{"a":1}' | od -c
0000000 # 223 t e x t 224 \n { " a " : 1 }
0000020 \n
0000021
%
这是转换:
% echo -e '# \x93text\x94\n{"a":1}' | sed 's/^\s*#.*//' | od -c
0000000 223 t e x t 224 \n { " a " : 1 } \n
0000017
%
请注意,sed 表达式中的点字符与十六进制 93 字符不匹配。但是,如果我包括 LC_ALL=C
:
% echo -e '# \x93text\x94\n{"a":1}' | LC_ALL=C sed 's/^\s*#.*//' | od -c
0000000 \n { " a " : 1 } \n
0000011
%
然后 sed 表达式中的点字符匹配十六进制 93 和十六进制 94 字符。 sed 文档部分 Locale Considerations 谈到括号表达式,但上面的行为似乎证明这个问题发生在其他地方。
有趣的是,删除而不是替换并没有显示这个问题:
% echo -e '# \x93text\x94\n{"a":1}' | sed '/^\s*#.*/d' | od -c
0000000 { " a " : 1 } \n
0000010
鉴于我操作的是带注释的 JSON 文件,我认为在 sed 语句中添加 LC_ALL=C
的解决方案是合理的。
所以,我的问题是: 正在使用 LC_ALL=C
我在进行非语言环境特定的 sed
转换时一直想使用的东西(就像适用于带注释的 JSON 文件)?如果没有,有什么替代方法可以避免我上面显示的问题?
我的环境:
- CentOS 7.3 [kernel-3.10.0-514.6.1.el7.x86_64]
- sed(GNU sed)4.2.2 [sed-4.2.2-5.el7.x86_64]
- Bash 4.2.46(1) [bash-4.2.46-21.el7_3.x86_64]
C 语言环境是一种特殊的语言环境,旨在成为最简单的语言环境。您也可以说,虽然其他语言环境适用于人类,但 C 语言环境适用于计算机。 在 C 语言环境中,字符是单字节,字符集是 ASCII
在某些系统上,POSIX 语言环境存在差异,例如 non-ASCII 个字符的排序顺序未定义。
所以 LC_ALL=C 是将非第 8 位字符考虑在内的安全方法。
查看比较
使用 LC,sed 算作字符的一部分
echo -e '# \x93text\x94\n{"a":1}' | LC_ALL=C sed 's/[^[:alnum:]]/[HERE:&] /g' | od -c
0000000 [ H E R E : # ] [ H E R E :
0000020 ] [ H E R E : 223 ] t e x t [
0000040 H E R E : 224 ] \n [ H E R E : {
0000060 ] [ H E R E : " ] a [ H E R
0000100 E : " ] [ H E R E : : ] 1 [
0000120 H E R E : } ] \n
没有 LC,sed 不计入要考虑的字符的一部分([[:alnum:]]
和 [^[:alnum:]]
不要 参见 第 8 位字符)
echo -e '# \x93text\x94\n{"a":1}' | sed 's/[[:alnum:]]/[HERE:&] /g' | od -c
0000000 # 223 [ H E R E : t ] [ H E R
0000020 E : e ] [ H E R E : x ] [ H
0000040 E R E : t ] 224 \n { " [ H E R E
0000060 : a ] " : [ H E R E : 1 ] }
0000100 \n
echo -e '# \x93text\x94\n{"a":1}' | sed 's/[^[:alnum:]]/[HERE:&] /g' | od -c
0000000 [ H E R E : # ] [ H E R E :
0000020 ] 223 t e x t 224 \n [ H E R E : {
0000040 ] [ H E R E : " ] a [ H E R
0000060 E : " ] [ H E R E : : ] 1 [
0000100 H E R E : } ] \n