【问题标题】:Check if any replacement done by `perl -i -pe`检查是否由`perl -i -pe`完成了任何替换
【发布时间】:2016-04-03 01:20:56
【问题描述】:

GNU sed 中,我可以显示搜索模式替换成功的结果。简单的例子如下:

echo -e "nginx.service\nmariadb.service\nphp-fpm.service" > something.conf;
sed -ri 's|(mariadb)(\.service)|postgresql-9.4\2|w sed-output.log' something.conf;
[[ -s sed-output.log ]] && echo "Pattern found and modified. $(cat sed-output.log)" || echo "Pattern not found.";

因为sed在处理多行时有限制,所以我切换到perl

echo -e "nginx.service\nmariadb.service\nphp-fpm.service" > something.conf;
perl -i -pe 's|(mariadb)(\.service)|postgresql-9.4\2|' something.conf;

上面的代码与sed 一样,但是我怎样才能将modified content ("postgresql-9.4.service") 放入文件中,或打印出来?

基本上我想要实现的是,在脚本执行后,它会告诉我它是否成功(以及实际替换的内容),如果没有,我将显示一条消息,说明找不到和替换的内容.


编辑:
突出显示我想获得(仅-)modified content,这表明我的脚本是成功的。因为使用perl -i -pe 's/pattern/replace/' file,我不知道它返回的是真还是假。当然,我可以简单地通过grep -E "/pettern/" 找出答案,但这不是问题。

【问题讨论】:

  • \2 在替换表达式中应该是 $2-w 会警告你这个错误。
  • 顺便说一下,s|mariadb(?=\.service)|postgresql-9.4| 更快,虽然我怀疑它在这里会很重要。
  • 当我使用-pWe 运行脚本测试时,确实建议使用 $1,只是想让两个脚本看起来相同。也是积极前瞻用法的一个很好的例子,我学到了一些东西,谢谢!

标签: regex bash perl sed


【解决方案1】:

替换完成时,此代码将抛出一个等于0的退出代码:

$ perl -i -pe '$M += s|(mariadb)(\.service)|postgresql-9.4\2|;END{exit 1 unless $M>0}' something.conf
$ echo $?
0

NO 替换完成时,return 代码将是 1:

$ perl -i -pe '$M += s|(maria)(\.service)|postgresql-9.4\2|;END{exit 1 unless $M>0}' something.conf
$ echo $?
1

来自Perldocumentation

一个END代码块被执行得越晚越晚,也就是perl之后 已经完成了程序的运行,就在解释器运行之前 被退出,即使它是由于 die() 函数而退出。 (但如果它通过 exec 转变为另一个程序,或者正在 被信号吹出水面——你必须自己把它困住(如果 你可以)。)你可能在一个文件中有多个 END 块——它们会 按定义的相反顺序执行;即:后进先出 (后进先出)。当您使用 -c 运行 perl 时,不会执行 END 块 切换,或者编译失败。

s operator返回的替换次数

s/PATTERN/REPLACEMENT/msixpodualngcer

在字符串中搜索模式,如果找到,则替换该模式 带有替换文本并返回替换的数量 制作。

【讨论】:

  • 作为对比,@Borodin 添加了一个BEGIN 代码块,它实际上允许它产生与/w sed-output.log 相同的结果。谢谢你的灵感。
【解决方案2】:

它在 Perl 中没有那么整洁,因为您必须显式地打开日志文件,并且对于必须位于 BEGIN 块中的单行代码。但是 Perl 的 s/// 返回所做更改的数量,因此您可以对其进行测试

还要注意,$2 在 Perl 中优于 \2,因为后者表示具有代码点 2 或 Unicode U+0002 的字符 START OF TEXT

perl -i -pe ' BEGIN { open F, ">perl-output.log" } print F $_ if s|(mariadb)(\.service)|postgresql-9.4$2| ' something.conf

【讨论】:

  • 简单测试的结果与/w sed-output.log相同。这是sed 代码行的替换,正是我正在寻找的!谢谢!
【解决方案3】:

如果只打印替换的行,可以直接检查输出:

if [[ -z $(sed -n 's/mariadb\(\.service\)/postgresql-9.4\1/p' something.conf) ]]; then
    echo nope
fi

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-18
    • 2021-08-10
    • 1970-01-01
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 2019-03-21
    • 1970-01-01
    相关资源
    最近更新 更多