【问题标题】:sed - delete from pattern1 before pattern2 to pattern3 after pattern2sed - 从 pattern2 之前的 pattern1 删除到 pattern2 之后的 pattern3
【发布时间】:2019-07-09 16:10:26
【问题描述】:

我正在尝试删除两个图案之间的线条,包括带有图案本身的线条,如果在它们之间找到另一个图案,但我不知道如何解决它。

假设我有如下输入,并且想要删除第 6 行到第 11 行,因为在模式 startend 之间找到了模式 notthis

start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
OgytsRhZbD8T
notthis
0PlcUh2RLvVW
tsz2S80SyW9p
end
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end

我将我认为我理解的内容从 this answer 更改为类似的内容,但它不起作用:

/^start$/{$!{N;/^start\n(.*\n)*notthis.*\n(.*\n)*end/d;ty;P;D;:y}}

是不是因为N 只是将初始模式^start$ 后面的行附加到模式空间而忽略了后面的内容?实现我想要的目标的正确方法是什么?

【问题讨论】:

  • 希望在编写包含/^start$/{$!{N;/^start\n(.*\n)*notthis.*\n(.*\n)*end/d;ty;P;D;:y}} 之类的符文的脚本时,当您自己思考时,会有一个重点——“我在做什么???”!

标签: regex awk sed multiline


【解决方案1】:

sed 用于对单个字符串进行简单替换,就是这样。对于其他任何你应该使用 awk 的东西,例如使用 GNU awk for mult-char RS 这个简短的脚本将从您发布的输入中生成您想要的输出:

$ awk 'BEGIN{RS=ORS="end\n"} !/notthis/' file
start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end

或者更清晰、更健壮、更容易使用任何 awk 进行增强:

$ cat tst.awk
/start/ { f = 1 }
f {
    rec = rec $0 ORS
    if ( /end/ ) {
        if ( rec !~ /notthis/ ) {
            printf "%s", rec
        }
        rec = ""
        f = 0
    }
}
$
$ awk -f tst.awk file
start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end

上述内容将在每个 UNIX 机器上的任何 shell 中使用任何 awk 有效且稳健地工作,如果/当您的需求发生变化时,易于理解和修改。

【讨论】:

  • 谢谢你,就像一个魅力。你介意解释一下吗?
  • 第一个读取一个完整的记录(多行文本块),每次记录以end\n 结尾,如果记录不包含notthis,则打印该记录。第二个在找到start 时设置一个标志,在设置该标志时一次建立一行记录,然后在找到end 时打印不包含notthis 的记录。浏览 awk 手册页后,如果您对语法有任何具体问题,请告诉我。
【解决方案2】:

这是另一个awk 脚本。希望匹配部分问题描述。

script.awk

BEGIN {omitMark = "notthis"}  # assign omit marker as ReqExp
/start/, /end/ {   # define RegExp range for omission section 
    if ($0 ~ omitMark) next;  # if matched omission marker skip processing
    print;  # print not ommited currnt line in section
    next;   # skip to process next line in section
}
1;  # print any line not in section.

input.txt

start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
OgytsRhZbD8T
notthis
0PlcUh2RLvVW
tsz2S80SyW9p
end
notthis
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
notthis
end
notthis

运行:

awk -f script.awk input.txt

输出:

start
AHBUe3Ar5NoD
3EcuCcD2QCja
7VmlKFbD8Rbi
end
start
OgytsRhZbD8T
0PlcUh2RLvVW
tsz2S80SyW9p
end
notthis
start
dQ5qiZCvBqcK
SufdS40X1Sh2
B1cyNshOj2Z4
end
notthis

【讨论】:

【解决方案3】:

这可能对你有用(GNU sed):

sed '/^start/{:a;N;/end$/!ba;/notthis/d}' file

收集startend 之间的行,如果它们包含字符串notthis,则删除它们。

【讨论】:

    猜你喜欢
    • 2012-06-13
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多