sed - 从 pattern2 之前的 pattern1 删除到 pattern2 之后的 pattern3
sed - delete from pattern1 before pattern2 to pattern3 after pattern2
我正在尝试删除两个模式之间的线条,包括带有模式本身的线条,如果在它们之间发现另一个模式,但我不确定如何解决它。
假设我有一个如下所示的输入并且想要删除第 6 行到第 11 行,因为在模式 start
和 end
之间找到了模式 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$
之后的行附加到模式 space 而忽略了后面的内容?实现我想要的目标的正确方法是什么?
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 [=11=] 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,上面的代码将有效且稳健地工作,易于理解并且修改起来很简单 if/when 您的需求更改。
这是另一个 awk
脚本。希望与部分问题描述相符。
script.awk
BEGIN {omitMark = "notthis"} # assign omit marker as ReqExp
/start/, /end/ { # define RegExp range for omission section
if ([=10=] ~ 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
这可能适合您 (GNU sed):
sed '/^start/{:a;N;/end$/!ba;/notthis/d}' file
收集 start
和 end
之间的行,如果它们包含字符串 notthis
则删除它们。
我正在尝试删除两个模式之间的线条,包括带有模式本身的线条,如果在它们之间发现另一个模式,但我不确定如何解决它。
假设我有一个如下所示的输入并且想要删除第 6 行到第 11 行,因为在模式 start
和 end
之间找到了模式 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$
之后的行附加到模式 space 而忽略了后面的内容?实现我想要的目标的正确方法是什么?
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 [=11=] 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,上面的代码将有效且稳健地工作,易于理解并且修改起来很简单 if/when 您的需求更改。
这是另一个 awk
脚本。希望与部分问题描述相符。
script.awk
BEGIN {omitMark = "notthis"} # assign omit marker as ReqExp
/start/, /end/ { # define RegExp range for omission section
if ([=10=] ~ 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
这可能适合您 (GNU sed):
sed '/^start/{:a;N;/end$/!ba;/notthis/d}' file
收集 start
和 end
之间的行,如果它们包含字符串 notthis
则删除它们。