在正则表达式中使用匹配组的长度
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($_)
。而chomp
returns是去掉的总字符数,由于$_
为空,所以没有去掉任何字符,也就是说这个chomp
returns0
.所以你基本上是在写 $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|
这应该有助于让您了解哪里出了问题。
假设这个
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($_)
。而chomp
returns是去掉的总字符数,由于$_
为空,所以没有去掉任何字符,也就是说这个chomp
returns0
.所以你基本上是在写 $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|
这应该有助于让您了解哪里出了问题。