Regex unicode的Perl命令行替换
我正在尝试使用shell脚本将每个单词(存储在名为Regex unicode的Perl命令行替换,regex,bash,perl,unicode,Regex,Bash,Perl,Unicode,我正在尝试使用shell脚本将每个单词(存储在名为\u id的tmp文件中)替换为一个数字。它可以很好地工作,但unicode单词除外,unicode单词会生成一个数字,但使用Perl进行替换不起作用。下面讨论的bash代码如下: x=0 for id in `cat _id`; do echo $x $id perl -p -i -e "s/\b$id\b/$x/g" x_graph.dot x=$(($x + 1)) done 有人能指出bug在哪里吗?请参阅:
\u id
的tmp文件中)替换为一个数字。它可以很好地工作,但unicode单词除外,unicode单词会生成一个数字,但使用Perl进行替换不起作用。下面讨论的bash代码如下:
x=0
for id in `cat _id`; do
echo $x $id
perl -p -i -e "s/\b$id\b/$x/g" x_graph.dot
x=$(($x + 1))
done
有人能指出bug在哪里吗?请参阅:
-C
[编号/列表]
-C
标志控制一些Perl Unicode特性:
I 1 STDIN is assumed to be in UTF-8
O 2 STDOUT will be in UTF-8
E 4 STDERR will be in UTF-8
S 7 I + O + E
i 8 UTF-8 is the default PerlIO layer for input streams
o 16 UTF-8 is the default PerlIO layer for output streams
D 24 i + o
A 32 the @ARGV elements are expected to be strings encoded
in UTF-8
因此,至少,您需要perl-COi
,但是perl-CSD
看起来更整洁
此外,您可能希望使用
u
根据Unicode规则匹配
用你的s//
。或者,写下:
perl-CSD-Mutf8-Mfeature=unicode_strings-p-i-e“s/\b$id\b/$x/g”x_图形.dot
请注意使用单引号而不是双引号,以避免意外插入
-Mutf8
(相当于):这将在源代码中启用UTF-8(-e
在您的情况下使用一个线性程序)-CSDA
:这将使perl
使用UTF-8作为输入和输出流的默认层LANG=en_US.UTF-8
echo“aób”>z.txt
id=o
x=
perl-CD-Mutf8-p-i-e“s/\b$id\b/$x/g”z.txt
cat z.txt
-C[编号/列表]-C标志控制一些Perl Unicode特性。
…
S 8 I+O+E[STDIN假定在UTF-8中,STDOUT和STDERR将在UTF-8中]
D 24 i+o[UTF-8是输入和输出流的默认PerlIO层]
32@ARGV元素应为字符串编码 在UTF-8中
假设您使用UTF-8编码了
é
(U+00E9):C3 A9
。由于不进行任何解码,因此可以获得由“\xC3\xA9”
生成的字符串
正则表达式-或者更确切地说是\b
、\w
、\d
等-期望输入为Unicode代码点,这意味着您正在有效地提供和,而不是U+00E9。U+00C3是单词字符,但U+00A9不是,因此第二个\b
与预期匹配的位置不匹配
因此,您需要对输入进行解码,并对输出进行编码<代码>-C为UTF-8提供了一种方便的方法
perl -i -CSDA -pe'
BEGIN {
($id, $x) = splice(@ARGV, 0, 2);
die "Bad id" if $id !~ /^\w(?:.*\w)?\z/s;
}
s/\b\Q$id\E\b/$x/g
' "$id" "$x" x_graph.dot
注:
- 通过使用命令行参数传递参数,我修复了一个注入错误
- 使用
假设\b
总是以$id
字符开始,并且总是以\w
字符结束,因此我添加了一个检查来验证该假设\w
- 通过使用
将id转换为正则表达式模式,我修复了一个注入错误\Q..\E
测试:
请提供必要的数据来说明问题。例如,将
\u id
和x\u graph.dot
减少为每行一行,然后提供od-t x1\u id x\u graph.dot
的输出。抛开规范化之类的考虑,如果将perl命令行中的-e
替换为-e
,那么至少可以在现代版本的perl中启用“unicode字符串”功能。我怀疑问题在于编码文本上使用了\b
,我认为任何正则表达式引擎在Unicode上都不能正确处理单词边界。在这种情况下,您必须滚动您自己的单词边界。不要通过删除\b
来修复编码问题!!!现在你有两个问题,谢谢!我还需要删除\b
(单词边界)以使其正常工作。这并不是我真正想要的,因为我会链接让它处理单词边界。因为$id
是一个shell变量,而不是perl变量,所以不能像那样用单引号将它括起来。如果要删除\b
,则不需要做任何其他更改@sinan-Ünür感谢解释中的错误修正:-)
$ printf "é\n" >_id
$ printf "[é]\n" >x_graph.dot
$ x=0
$ id=`cat _id`
$ perl -i -CSDA -pe'
BEGIN {
($id, $x) = splice(@ARGV, 0, 2);
die "Bad id" if $id !~ /^\w(?:.*\w)?\z/s;
}
s/\b\Q$id\E\b/$x/g
' "$id" "$x" x_graph.dot
$ cat x_graph.dot
[0]