sed - 搜索和替换多行

时间:2017-12-30 00:06:51

标签: bash sed

我今天刚刚从旧问题中了解到SED如何为单线工作。但是现在我试图为多行(php文件缩进)做同样的事情并且它不起作用。应该怎么做?

代码:

if ( empty( $donot_dump ) ) {
                return false;

替换为:

if ( empty( $donot_dump ) ) {
                return true;

文件名:class-prompt.php

由于这是一个大文件,因此有返回false的TONS;并返回true;这就是为什么我不能让所有回报真实,反之亦然。

4 个答案:

答案 0 :(得分:5)

sed '/if ( empty( $donot_dump ) )/ { N; s/false/true/ }' data
    只有当该行与/regex/ cmd 匹配时,
  • cmd才会执行regex
  • { cmds }是一组命令
  • N命令将文件的下一行追加到模式空间
  • s/regex/replacement/regex替换为replacement

换句话说,此sed会检查您所需的if语句。如果找到它,它会在{ ... }内执行一组命令。第一个命令N将下一行附加到模式空间,第二个命令sfalse替换为true

此解决方案适用于GNU sed。如SigmaPiEpsilon的answer中所述,此处不需要N命令,请谨慎使用。我使用它来支持n,因为它为您提供了我认为可能派上用场的选项。您可以在sed manual或此sed tutorial中了解详情。

答案 1 :(得分:0)

关于sed多行N的注意事项以及有类似问题的人的替代方案。这里不一定需要多行版本的sed N命令。由于要替换的文本位于下一行,因此单行next(n)命令足够。如果要替换的文本也出现在原始行中,也可能必要。这是因为多行N命令会将下一行拉入模式空间并在组合行上执行替换。单行next(n)命令仅作用于下一行。下面说明了N执行错误替换的情况:

$ cat class_prompt.php
if ( empty( $donot_false_dump ) ) {
                return false;
$ sed '/if ( empty( \$donot_false_dump ) ) {/{ N; s/false/true/ }' class_prompt.php
if ( empty( $donot_true_dump ) ) {
                return false;
$ sed '/if ( empty( \$donot_false_dump ) ) {/{ n; s/false/true/ }' class_prompt.php
if ( empty( $donot_false_dump ) ) {
                return true;

仅当搜索模式延伸到多行时,才需要多线N.

这也可以在perl中完成。如下所示

$ perl -pe 'if ($p) { s/false/true/ ; $p=0 } $p++ 
> if /if \( empty\( \$donot_false_dump \) \) {/ ' class_prompt.php
if ( empty( $donot_false_dump ) ) {
                return true;

答案 2 :(得分:0)

使用sed应该。 sed用于单个行上的简单替换,即全部。当你用它做任何其他事情时,你会使用在20世纪80年代当awk被发明时变得过时的结构,并且通常是不可移植且效率低下的,并且不能建立其他任何东西。

鉴于此输入文件:

$ cat file
foo
if ( empty( $donot_dump ) ) {
                return false;
bar

在OSX上使用当前接受的sed答案:

$ sed '/if ( empty( $donot_dump ) )/ { N; s/false/true/ }' file
sed: 1: "/if ( empty( $donot_dum ...": bad flag in substitute command: '}'

在任何UNIX机器上的任何shell中都有任何awk:

$ awk 'f{sub(/false/,"true"); f=0} /if ( empty( $donot_dump ) )/{f=1} 1' file
foo
if ( empty( $donot_dump ) ) {
                return false;
bar

但实际上整个方法都容易出错,因为它使用正则表达式而不是字符串比较并进行部分匹配而不是完全匹配,并且只能用于匹配2行。如果您对执行此类任务的一般,强大的解决方案感兴趣,请发布一个新问题。

答案 3 :(得分:0)

检查第一个if语句,如果找到,则替换下一行。

关于Sed的替换标志,g,替换所有出现次数。

$ sed 's/test/another test/g' myfile

w flag:表示将结果写入文件。

$ sed 's/test/another test/2' myfile

我从这个sed tutorial中获取了这些例子。