Não tente usar grep para isso, use awk. Para combinar 2 regexps R1 e R2 no grep, você pensaria que seria:
grep 'R1.*R2|R2.*R1'
enquanto no awk seria:
awk '/R1/ && /R2/'
mas e se se R2
sobrepuser a ou é um subconjunto de R1
? Esse comando grep simplesmente não funcionaria enquanto o comando awk funcionaria. Digamos que você deseja encontrar linhas que contenham the
e heat
:
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
Você precisaria usar 2 greps e um pipe para isso:
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
e, é claro, se você realmente exigiu que eles fossem separados, você sempre pode escrever no awk o mesmo regexp que você usou no grep e existem soluções alternativas do awk que não envolvem repetir os regexps em todas as seqüências possíveis.
Deixando isso de lado, e se você quisesse estender sua solução para corresponder a três regexps R1, R2 e R3. No grep, essa seria uma dessas más escolhas:
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
enquanto no awk, seria conciso, óbvio, simples, eficiente:
awk '/R1/ && /R2/ && /R3/'
Agora, e se você realmente quisesse combinar as cadeias literais S1 e S2 em vez das regexps R1 e R2? Você simplesmente não pode fazer isso em uma chamada para grep, você deve escrever um código para escapar de todos os metacarpos do RE antes de chamar grep:
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
ou use 2 greps e um pipe:
grep -F 'S1' file | grep -F 'S2'
que novamente são más escolhas, enquanto que com o awk você simplesmente usa um operador de string em vez do operador regexp:
awk 'index($0,S1) && index($0.S2)'
Agora, e se você quisesse corresponder 2 regexps em um parágrafo em vez de uma linha? Não pode ser feito no grep, trivial no awk:
awk -v RS='' '/R1/ && /R2/'
Que tal um arquivo inteiro? Novamente, não pode ser feito em grep e trivial em awk (desta vez, estou usando o GNU awk para multi-char RS por concisão, mas não há muito mais código em nenhum awk ou você pode escolher um char de controle que você sabe que não estar na entrada para o RS fazer o mesmo):
awk -v RS='^$' '/R1/ && /R2/'
Portanto, se você deseja encontrar vários regexps ou strings em uma linha ou parágrafo ou arquivo, não use grep, use awk.