我想以特定方式过滤命令的输出。我们假设以下输出:
==== Foo ====
Line to filter 1
Line to filter 2
Line to filter 3
Line to filter 4
Line to filter 5
==== Bar ====
Line to filter 6
Line to filter 7
Line to filter 8
Line to filter 9
Line to filter 10
我要做的是使用一个命令Lines to filter 1-5
进行过滤,具体取决于命令中的“参数”是Foo还是Bar。例如:
command | grep '... Foo ...'
,输出:
Line to filter 1
Line to filter 2
Line to filter 3
Line to filter 4
Line to filter 5
command | grep '... Bar ...'
,输出:
Line to filter 6
Line to filter 7
Line to filter 8
Line to filter 9
Line to filter 10
有可能这样做吗?谢谢!
答案 0 :(得分:1)
你可以做很多这样的方法。使用awk:
awk -v s="Foo" '/^=/&&$2!=s { p=0 } p==1; /^=/&&$2==s { p=1 }' input.txt
这使用标记p
,根据找到的任何标题行的内容进行切换。
第二种方法(从我喜欢的123&#39删除的答案中肆无忌惮地被盗)要短得多:
awk -v s="$var" '/^=/{p=$0~s;next} p'
这个awk脚本有两个表达式 - 第一个将p
设置为评估$0~s
的布尔结果,如果p
为真,则第二个打印该行。 p
仅更改标题行。我想不出用awk表达这个任务的简短方法。
sed
中的方法可能是:
sed -ne '/^==== Foo/,/^====/{;/^====/d;p;}' input.txt
但是你无法将变量传递给sed,所以你要为此重写你的实际脚本,这有点丑陋。如果您想在bash中清理输入,可以使用参数扩展来完成。例如,您可以剥离任何非字母数字字符,如果您非常确定您希望在标题中看到的内容:
s="##Fo@o! "
sed -ne "/^==== ${s//[^[:alnum:]]/}/,/^====/{;/^====/d;p;}" input.txt
当然,sed
和awk
可以从 bash获得,但它们并不代表bash脚本。这也可以单独用bash完成:
s="Foo"; p=false
while read line; do
[[ $line =~ ^==== ]] && p=false
$p && echo "$line"
[[ $line =~ ^====\ $s ]] && p=true
done < input.txt
这遵循上面awk
脚本的示例,设置一个根据我们看到的标题切换的布尔值。