Reputation: 9
I want to filter the output of a command in a specific way. Let's suppose the following output:
==== 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
What I'm trying to do is to filter with one command the Lines to filter 1-5
depending if the "parameter" in the command is Foo or Bar. For example:
command | grep '... Foo ...'
, output:
Line to filter 1
Line to filter 2
Line to filter 3
Line to filter 4
Line to filter 5
command | grep '... Bar ...'
, output:
Line to filter 6
Line to filter 7
Line to filter 8
Line to filter 9
Line to filter 10
Is there a possible way to do it? Thank you!
Upvotes: 1
Views: 122
Reputation: 46826
So many ways you could do this. Using awk:
awk -v s="Foo" '/^=/&&$2!=s { p=0 } p==1; /^=/&&$2==s { p=1 }' input.txt
This uses a marker, p
, that gets toggled based on the content of any header line it finds.
A second approach (brazenly stolen from from 123's deleted answer, which I liked) is much shorter:
awk -v s="$var" '/^=/{p=$0~s;next} p'
This awk script has two expressions - the first sets p
to the boolean result of the evaluation $0~s
, and the second prints the line if p
is true. p
only changes on header lines. I can't think of a shorter way to express this task in awk.
An approach in sed
might be:
sed -ne '/^==== Foo/,/^====/{;/^====/d;p;}' input.txt
But you can't pass variables in to sed, so you'd be rewriting your actual script for this, which is a little uglier. If you wanted to sanitize your input in bash, you could do so using parameter expansion. For example, you could strip any non-alphanumeric characters, if you're pretty sure that's what you expect to see in titles:
s="##Fo@o! "
sed -ne "/^==== ${s//[^[:alnum:]]/}/,/^====/{;/^====/d;p;}" input.txt
Of course, sed
and awk
are available from bash, but they don't represent bash scripting. This could be done in bash alone, too:
s="Foo"; p=false
while read line; do
[[ $line =~ ^==== ]] && p=false
$p && echo "$line"
[[ $line =~ ^====\ $s ]] && p=true
done < input.txt
This follows the example of the awk
script above, setting a boolean which gets toggled depending on what header we see.
Upvotes: 1