i use a command for generating a list to STDOUT. this list looks like:
12345 stable
678
231
123
testing
2323
12345678 next
what i want is having only a match if the word testing AND stable are both in this list. so currently i do is:
grep -e stable -e testing
but this also matches if only one string is in the list. so this produce exit0 also if one string is not there (which is not wanted) what i want is that grep has exit1 as code $? if not two strings/words are found. so i need a dedicated and search here.
so what i want in PSEUDOCODE:
IF BOTHWORDS are there then;
EXITCODE=0
otherwise
EXITCODE=1
do you have an idea how to solve?
CodePudding user response:
The problem is that (by default) grep is line-oriented. You want to search several lines as one block of text.
With GNU grep, use the -z
option to delimit lines by the null-byte instead of newline.
Also, since both words must appear, your pattern has to be more complex:
produce_output() {
echo "12345 stable
678
231
123
testing
2323
12345678 next
"
}
# "stable" followed by "testing", or "testing" followed by "stable"
regex='(stable.*testing)|(testing.*stable)'
produce_output | grep -q -E "$regex" && echo found || echo not found
# => not found
produce_output | grep -z -q -E "$regex" && echo found || echo not found
# => found
To get the exit status:
grep -z -q -E "$regex"
exitCode=$?
But you usually don't need to do that explicitly.
awk provides an alternate solution that is nicely readable:
produce_output | awk '/stable/ {s } /testing/ {t } END {exit !(s > 0 && t > 0)}'
CodePudding user response:
In the simplest case, assuming stable
always occurs before next
-
$: sed -n '/stable/,${ /next/q0; }; $q1;' file && echo found both || echo no match
found both
If they could be in reverse order, add a second scan with arguments switched.
$: sed -n '/stable/,${ /next/q0; }; /next/,${ /stable/q0; }; $q1;' file
Sometimes it's easier to write your own logic.
It would be trivial to do in awk
as well.
$: awk '/stable/{s } /next/{n } s&&n{exit 0} END { if(!(s&&n)){exit 1} }' file && echo found both || echo no match