【问题标题】:Print strings alongside math results in s// substitution with the /e modifier在数学结果旁边打印字符串,用 /e 修饰符替换 s//
【发布时间】:2018-07-01 15:00:22
【问题描述】:

我正在尝试编写一个非常简单的单行来查找以下情况:

foo N 

并将它们替换为

foo N-Y 

例如,如果我有 3 个文件,其中包含以下行:

foo 5
foo 3
foo 9 

脚本以 Y=4 运行后,行将变为:

foo 1
foo -1
foo 5

我偶然发现了一个现有线程,该线程建议使用 /e 在替换命令的替换一半中运行代码,并且能够有效地从我的所有匹配项中减去 Y,但我不知道如何最好地将“foo”打印回来到文件中,因为当我尝试将 foo 和数字分成两个捕获组并将它们打印回来时,perl 认为我正在尝试将它们相乘并想要一个运算符。

这是我所在的位置:

find . -iname "*somematch*" -exec perl -pi -e 's/(Foo *)(\d+)/$1$2-4/e' {} \;

这当然行不通,“Scalar 找到了运算符在 -e 第 1 行的预期位置,靠近”$1$2。 >

编辑:更具体地说,如果我启用了 /e 选项以便能够在替换中执行数学运算,是否有一种简单的方法可以在另一个捕获组中打印字符串没有它试图对其进行数学运算的替换?

或者,是否有一种简单的方法可以仅对部分模式进行替换?我尝试将 m// 和 s/// 结合起来以实现结果,但最终无济于事。

【问题讨论】:

    标签: perl


    【解决方案1】:

    替换部分被视为/e 下的代码,因此它需要使用合法语法编写,就像您在程序中使用的那样。写 $t$v 是不合法的语法($1$2 在你的正则表达式中)。

    连接字符串的一种方法是$t . $v。然后您还需要在加法周围加上括号,因为按照优先规则,字符串$1$2 首先连接起来,然后尝试添加该字母数字字符串,从而产生警告。所以

    perl -i -pe's/(Foo *)([0-9]+)/$1.($2-4)/e'
    

    我将\d 替换为[0-9],因为\d 匹配来自所有Unicode 的各种“数字”,这似乎不是您需要的。


    如果数学出现在模式的其余部分之后,还有另一种方法,就像在您的示例中那样

    perl -i -pe's/Foo *\K([0-9]+)/$1-4/e'
    

    这里的\Kpositive lookbehind 的一种形式,它会丢弃该锚点之前的所有匹配项,因此不会消耗它们。因此,根据需要仅替换 [0-9]+

    【讨论】:

    • 谢谢!解决方案当然效果很好,我知道这是一件令人尴尬的简单事情正在逃避我。先做数学然后连接结果正是我想要的。
    • @Asterdahl 欢迎您:)。这并不令人尴尬——它可能会让人感到困惑,因为它在正则表达式中。注意\K 工具,它有时非常有用。如果出现问题,请告诉我。
    猜你喜欢
    • 2014-02-16
    • 2013-03-05
    • 1970-01-01
    相关资源
    最近更新 更多