Perl正则表达式命令行问题

6

我正在尝试在perl命令行中使用负向前瞻:

echo 1.41.1 | perl -pe "s/(?![0-9]+\.[0-9]+\.)[0-9]$/2/g"

获取一个类似于这样的增量版本:

1.41.2

然而它只是返回给我:

![0-9]+\.[0-9]+\.: event not found

我在 regex101(PCRE) 上尝试过它,结果很好,所以我不确定为什么它在这里不起作用。

2
顺便说一句,如果你想要增加一个数字,那就这么做,不要硬编码一个数字。(另外,为什么要使用lookaround?只需使用\K匹配并丢弃即可)-- s/[0-9]+\.[0-9]+\.\K([0-9]+)/$1+1/e; - zdim
参见:https://dev59.com/o2kv5IYBdhLWcg3w91hF,https://dev59.com/yWgu5IYBdhLWcg3w3ana,https://dev59.com/pIHba4cB1Zd3GeqPYPQC,https://stackoverflow.com/questions/43987641... - Wiktor Stribiżew
4个回答

6
在Bash中,!是“历史扩展字符”,除非使用反斜杠或单引号进行转义。(双引号不会禁用此功能;也就是说,在双引号内支持历史扩展。请参阅Bash中单引号和双引号的区别)
因此,只需将双引号更改为单引号即可:
echo 1.41.1 | perl -pe 's/(?![0-9]+\.[0-9]+\.)[0-9]$/2/g'

并且,就这样:

1.41.2

你也可以在当前 shell 中使用 set +H 来禁用 ! 历史扩展。而 shopt -s histreedit 则允许你编辑失败的历史扩展,而不仅仅是将输入的命令丢弃。 - melpomene

4
我猜这个表达也可能起作用:
([0-9.]+)\.([0-9]+)

测试

perl -e'
    my $name = "1.41.1";
    $name =~ s/([0-9.]+)\.([0-9]+)/$1\.2/;
    print "$name\n";
    '

输出

1.41.2

请在此处查看演示。


1
谢谢Emma!这个可以用,但单引号会更直接。 - Allen
2
@Allen 呃,你也有单引号...但是这里真的不需要正向或反向预查。 - zdim

4
如果您想“增加”一个数字,那么不能硬编码新值,而是需要捕获当前值并将其增加。
echo "1.41.1" | perl -pe's/[0-9]+\.[0-9]+\.\K([0-9]+)/$1+1/e'

在这里,/e修饰符使得替换部分被评估为代码,我们可以对捕获的数字进行+1,然后进行替换。 \K会丢弃先前的匹配项,因此我们不需要将它们放回; 参见“Perlre中的扩展模式”中的Lookaround Assertions
环视有时正是您想要的东西,但它们增加了正则表达式的复杂性(仅仅通过出现),可能很难正确使用,并且会影响效率。 这里不需要它们。
您得到的奇怪输出是因为双引号用于Perl程序“邀请”shell查看其中的内容,从而将其解释为历史记录扩展并运行该命令,如ruakh的帖子所述。

0
作为前瞻的替代方案,我们可以使用捕获组,例如以下代码将版本号捕获到3个捕获组中。
(\d+)\.(\d+)\.(\d+)

如果您想要输出捕获的版本号,可以这样写:
\1.\2.\3

仅将第三部分替换为数字"2"即可:

\1.\2.2

为了适应楼主的问题,它将是:

$ echo 1.14.1 | perl -pe 's/(\d+)\.(\d+)\.(\d+)/\1.\2.2/'
1.14.2
$

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接