我不确定这是否已经存在,但我在尝试表达我想在搜索字段中完成的工作时遇到了一些麻烦。
说我有一个类似以下的文件
foo1
foo2
foo3
barbarbar
barbarbar
barbarbar
foo4
foo5
barbarbar
barbarbar
barbarbar
foo6
foo7
我想在“foo#”之后只获得除“foo#”之外的字段。我还希望打印“foo#”如果它后面有条形栏并且直到下一个“foo#”。示例输出将在下面。
foo3
barbarbar
barbarbar
barbarbar
foo5
barbarbar
barbarbar
barbarbar
答案 0 :(得分:2)
看起来这个sed
命令可以正常工作:
sed -n '/^foo[0-9]$/{N;:l;/\nfoo[0-9]$/{D;bl};p;b};p'
老实说,我很遗憾试图用sed
做到这一点,结果难以理解。
/^foo[0-9]$/{ # if a line matches fooX
N # retrieve another line
:l # we'll jump to here later ; label l
/\nfoo[0-9]$/{ # if the following line matches fooX too
D # discard the first line and consume another one
bl # jump back to l
} # at this point we have a fooX line followed by a non-fooX line
p # print what we've matched
b # stop processing this line (jump to the end of the script)
} # reached when the first line read doesn't match fooX
p # print the line
编辑:既然我已经这样做了,我注意到p;b
部分可以删除,因为它会通过到达最后p
来表现相同。如果我是一个不得不维持这个的可怜的灵魂,我想我宁愿在那里拥有它。
答案 1 :(得分:1)
我通常不想发布“未尝试过”的问题的答案,但我有一些时间在我的手上。我喜欢用awk这样的东西:
“状态机”方法:
awk '
/foo/ && afterfoo != "" { print currentfoo; print afterfoo; afterfoo = "" }
/foo/ { currentfoo = $0 }
!/foo/ { afterfoo = afterfoo $0 "\n" }
END { if (afterfoo != "") {print currentfoo; print afterfoo} }
' file
“逆过程逆转”方法:
tac file | awk '
!/foo/ { print; seenfoo = 0 }
/foo/ && !seenfoo++
' | tac