在正则表达式中使用匹配组的长度

Using the length of the matched group inside regex

假设这个

char=l
string="Hello, World!"

现在,我想替换 string 中的所有 char,但在读取 STDIN

时连续出现(运行-长度编码)

我试过这个:

$c=<>;$_=<>;print s/($c)*/length($&)/grse;

当输入为

l
Hello, World!

它returns Hello, World!。但是当我 运行 这个

$c=<>;$_=<>;print s/(l)*/length($&)/grse;

它返回了 He2o, Wor1d

所以,由于输入是在不同的行中给出的,$c 包含 \n(用 $c=~/\n/ 检查) 所以,我尝试了

$c=<>.chomp;$_=<>;print s/($c)*/length($&)/grse;

$c=<>;$_=<>;print s/($c.chomp)*/length($&)/grse;

都没用。谁能说说为什么?

在 Perl 中,. 用于连接字符串,而不是调用方法(与某些其他语言不同;例如 Ruby)。看看 documentation of chomp 看看它应该如何使用。你应该做

chomp($c=<>)

而不是

$c=<>.chomp

您的完整代码应该是:

chomp($c=<>);$_=<>;print s/($c)*/length($&)/grse;

如果 $c 始终是单个字符,则正则表达式可以简化为 s/$c+/length($&)/grse。此外,如果 $c 可以是正则表达式元字符(例如,+*([ 等),那么你应该转义它(为了以防万一,逃避它是有意义的)。为此,您可以使用 \Q..\E(或 quotemeta,尽管它更冗长,因此可能不太适合单行代码):

s/\Q$c\E+/length($&)/grse

如果您不以某种方式转义 $c,并且您的一行代码是 运行,例如第一个输入是 (,您将得到以下内容错误:

Quantifier follows nothing in regex; marked by <-- HERE in m/(+ <-- HERE / at -e line 1, <> line 2

关于 $c=<>.chomp 在 Perl 中的实际含义(因为这是在某些情况下有意义的有效 Perl 代码):

$c=<>.chomp 表示 <> 连接到 chomp,其中没有参数的 chomp 被理解为 chomp($_)。而chompreturns是去掉的总字符数,由于$_为空,所以没有去掉任何字符,也就是说这个chompreturns0.所以你基本上是在写 $c=<>.0,这意味着如果你的输入是 l\n,你最终会得到 l\n0 而不是 l

自己调试此类问题的一种方法是:

  • 使用 -w 标志启用警告。在那种情况下,它会打印

    Use of uninitialized value $_ in scalar chomp at -e line 1, <> line 1.
    

    这可以说不是有史以来最有用的警告,但它可以帮助您了解错误所在。

  • 打印变量以确保它们包含您期望的内容。例如,您可以 co perl -wE '$c=<>.chomp;print"|$c|"',这将打印:

    |l
    0|
    

    这应该有助于让您了解哪里出了问题。