No intentes usar grep para esto, usa awk en su lugar. Para unir 2 expresiones regulares R1 y R2 en grep, pensarías que sería:
grep 'R1.*R2|R2.*R1'
mientras que en awk sería:
awk '/R1/ && /R2/'
pero ¿qué R2
pasa si se superpone o es un subconjunto de R1
? Ese comando grep simplemente no funcionaría mientras que el comando awk sí. Digamos que desea encontrar líneas que contengan the
y heat
:
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
Tendría que usar 2 greps y una tubería para eso:
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
y, por supuesto, si realmente hubiera requerido que estuvieran separados, siempre puede escribir en awk la misma expresión regular que usó en grep y hay soluciones alternativas awk que no implican repetir las expresiones regulares en cada secuencia posible.
Dejando eso de lado, ¿y si quisieras extender tu solución para que coincida con 3 expresiones regulares R1, R2 y R3? En resumen, esa sería una de estas malas elecciones:
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
mientras que en awk sería conciso, obvio, simple y eficiente:
awk '/R1/ && /R2/ && /R3/'
Ahora, ¿qué pasa si realmente quisiera hacer coincidir las cadenas literales S1 y S2 en lugar de las expresiones regulares R1 y R2? Simplemente no puede hacer eso en una llamada a grep, debe escribir el código para escapar de todos los metacares RE antes de llamar a grep:
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
o de nuevo use 2 greps y una pipa:
grep -F 'S1' file | grep -F 'S2'
que de nuevo son malas elecciones, mientras que con awk simplemente usa un operador de cadena en lugar del operador regexp:
awk 'index($0,S1) && index($0.S2)'
Ahora, ¿qué pasaría si quisieras unir 2 expresiones regulares en un párrafo en lugar de una línea? No se puede hacer en grep, trivial en awk:
awk -v RS='' '/R1/ && /R2/'
¿Qué tal en todo un archivo? Una vez más, no se puede hacer en grep y trivial en awk (esta vez estoy usando GNU awk para RS de múltiples caracteres por concisión, pero no es mucho más código en ningún awk o puedes elegir un control-char que sabes que no estar en la entrada para que el RS haga lo mismo):
awk -v RS='^$' '/R1/ && /R2/'
Entonces, si desea encontrar múltiples expresiones regulares o cadenas en una línea, párrafo o archivo, no use grep, use awk.