Regex unicode的Perl命令行替换

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在哪里吗?请参阅:

我正在尝试使用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在哪里吗?

请参阅:

-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
      字符结束,因此我添加了一个检查来验证该假设

    • 通过使用
      \Q..\E
      将id转换为正则表达式模式,我修复了一个注入错误


    测试:


    请提供必要的数据来说明问题。例如,将
    \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]