ein*_*lum 9 grep sed awk text-processing pattern-matching
这个问题的答案:
不关心落在匹配模式之间的多个行序列。因此,例如,sed -n '/startpattern_here/,/endpattern_here/p'
将打印位于这些模式出现之间的几个行序列。
但是,假设我只想打印文件中的最后一个这样的序列。我可以用 sed 做到这一点吗?如果没有,我想可能是awk?还有什么?
笔记:
tac 和 awk 的结合
tac file \
| awk '
!p && /endpattern_here/ {p = 1}
p {print}
p && /startpattern_here/ {exit}
' \
| tac
Run Code Online (Sandbox Code Playgroud)
这可能有效,假设您想要一个完整的正则表达式测试:
awk '/startpattern_here/ {buf="";f=1}
f{buf=buf $0 "\n"}
/endpattern_here/ {f=0; lastcomplete=buf}
END{printf("%s",lastcomplete)}' file.txt
Run Code Online (Sandbox Code Playgroud)
这将确保仅打印完整的起止模式。
测试用例:
irrelevant
irrelevant
irrelevant
startpattern_here
relevant_but_dont_show_1
relevant_but_dont_show_1
relevant_but_dont_show_1
endpattern_here
irrelevant
irrelevant
startpattern_here
relevant_but_dont_show_2
relevant_but_dont_show_2
relevant_but_dont_show_2
endpattern_here
irrelevant
irrelevant
startpattern_here
relevant_and_show
relevant_and_show
relevant_and_show
endpattern_here
irrelevant
startpattern_here
incomplete_dont_show
Run Code Online (Sandbox Code Playgroud)
结果:
startpattern_here
relevant_and_show
relevant_and_show
relevant_and_show
endpattern_here
Run Code Online (Sandbox Code Playgroud)
注意如果您想抑制开始和结束模式的输出,只需交换规则/startpattern_here/ { ... }
and /endpattern_here/ { ... }
,即首先放置“结束模式”规则,然后将“开始模式”规则放在END
规则之前。
使用Ex(一个 POSIX 编辑器)非常简单:
printf '%s\n' 1 '?END?' '?START?,.p' | ex -s file
Run Code Online (Sandbox Code Playgroud)
1
转到文件的第一行。如果END
是文件的最后一行,则这是必要的。
?END?
为 向后寻找(环绕文件结尾)END
,从而找到它在文件中的最后一次出现。
?START?,.p
打印从前一个START
地址到当前地址的所有内容。
下面是一个使用 here-docs 而不是 的示例printf
,只是为了多样性。
$ cat file
zdk
START
b12
END
kdn
START
000
111
END
START
ddd
Run Code Online (Sandbox Code Playgroud)
$ ex -s file <<EOF
> 1
> ?END?
> ?START?,.p
> EOF
START
000
111
END
Run Code Online (Sandbox Code Playgroud)
看来我只能使用tac
:
tac | sed -n '/endpattern_here/,/startpattern_here/ {p; /startpattern_here/q;}' | tac
Run Code Online (Sandbox Code Playgroud)
感谢 @glenn jackman 和 @Quasimodo 帮助我正确调用 sed。
一种方法是简单地存储每组,用下一组覆盖它,并在到达最后时打印您保留的组:
awk '{
if(/startpattern_here/){
a=1;
lines=$0;
next
}
if(a){
lines=lines"\n"$0
}
if(/end_pattern/){
a=0
}
}
END{
print lines
}' file
Run Code Online (Sandbox Code Playgroud)
例如,使用此测试文件:
startpattern_here
line 1
line 2
line 3
end_pattern
startpattern_here
line 1b
line 2b
line 3b
end_pattern
startpattern_here
line 1c
line 2c
line 3c
end_pattern
Run Code Online (Sandbox Code Playgroud)
我得到:
$ awk '{ if(/startpattern_here/){a=1; lines=$0; next} if(a){lines=lines"\n"$0} if(/end_pattern/){a=0}} END{print lines}' file
startpattern_here
line 1c
line 2c
line 3c
end_pattern
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
810 次 |
最近记录: |