Non provare a usare grep per questo, usa invece awk. Per abbinare 2 regexps R1 e R2 in grep penseresti che sarebbe:
grep 'R1.*R2|R2.*R1'
mentre in awk sarebbe:
awk '/R1/ && /R2/'
ma cosa succede se si R2
sovrappone o è un sottoinsieme di R1
? Quel comando grep semplicemente non avrebbe funzionato mentre il comando awk avrebbe funzionato. Diciamo che vuoi trovare linee che contengono the
e heat
:
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
Dovresti usare 2 greps e una pipe per quello:
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
e ovviamente se avevi richiesto loro di essere separati, puoi sempre scrivere in awk lo stesso regexp usato in grep e ci sono soluzioni awk alternative che non implicano la ripetizione dei regexps in ogni possibile sequenza.
Mettendolo da parte, cosa succede se si desidera estendere la soluzione per abbinare 3 regexps R1, R2 e R3. In grep sarebbe una di queste povere scelte:
grep 'R1.*R2.*R3|R1.*R3.*R2|R2.*R1.*R3|R2.*R3.*R1|R3.*R1.*R2|R3.*R2.*R1' file
grep R1 file | grep R2 | grep R3
mentre in awk sarebbe il conciso, ovvio, semplice, efficiente:
awk '/R1/ && /R2/ && /R3/'
Ora, cosa succederebbe se davvero volessi abbinare le stringhe letterali S1 e S2 invece di regexps R1 e R2? Semplicemente non puoi farlo in una chiamata a grep, devi scrivere il codice per sfuggire a tutti i metachar RE prima di chiamare grep:
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
o ancora usa 2 greps e una pipa:
grep -F 'S1' file | grep -F 'S2'
che di nuovo sono scelte sbagliate mentre con awk usi semplicemente un operatore stringa invece dell'operatore regexp:
awk 'index($0,S1) && index($0.S2)'
E se volessi abbinare 2 regexps in un paragrafo anziché in una riga? Non può essere fatto in grep, banale in awk:
awk -v RS='' '/R1/ && /R2/'
Che ne dici di un intero file? Di nuovo non può essere fatto in grep e banale in awk (questa volta sto usando GNU awk per RS multi-char per concisione, ma non c'è molto più codice in qualsiasi awk o puoi scegliere un control-char che sai che non lo farà essere nell'input affinché RS faccia lo stesso):
awk -v RS='^$' '/R1/ && /R2/'
Quindi - se vuoi trovare più regexps o stringhe in una riga, in un paragrafo o in un file, non usare grep, usa awk.