N'essayez pas d'utiliser grep pour cela, utilisez plutôt awk. Pour faire correspondre 2 expressions rationnelles R1 et R2 dans grep, vous penseriez que ce serait:
grep 'R1.*R2|R2.*R1'
alors qu'en awk ce serait:
awk '/R1/ && /R2/'
mais que se passe-t-il si R2
chevauche ou est un sous-ensemble de R1
? Cette commande grep ne fonctionnerait tout simplement pas alors que la commande awk le ferait. Disons que vous voulez trouver des lignes qui contiennent the
et heat
:
$ echo 'theatre' | grep 'the.*heat|heat.*the'
$ echo 'theatre' | awk '/the/ && /heat/'
theatre
Il faudrait utiliser 2 greps et un pipe pour ça:
$ echo 'theatre' | grep 'the' | grep 'heat'
theatre
et bien sûr, si vous aviez réellement demandé qu'ils soient séparés, vous pouvez toujours écrire dans awk la même expression régulière que celle utilisée dans grep et il existe des solutions alternatives à awk qui n'impliquent pas de répéter les expressions rationnelles dans chaque séquence possible.
Mis à part cela, que se passe-t-il si vous souhaitez étendre votre solution pour correspondre à 3 regexps R1, R2 et R3. En grep, ce serait l'un de ces mauvais choix:
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
alors qu'en awk, ce serait concis, évident, simple, efficace:
awk '/R1/ && /R2/ && /R3/'
Maintenant, que se passe-t-il si vous vouliez réellement faire correspondre les chaînes littérales S1 et S2 au lieu des expressions rationnelles R1 et R2? Vous ne pouvez tout simplement pas faire cela en un seul appel à grep, vous devez soit écrire du code pour échapper à toutes les métachars RE avant d'appeler grep:
S1=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R1')
S2=$(sed 's/[^^]/[&]/g; s/\^/\\^/g' <<< 'R2')
grep 'S1.*S2|S2.*S1'
ou encore utiliser 2 greps et un pipe:
grep -F 'S1' file | grep -F 'S2'
qui sont encore de mauvais choix alors qu'avec awk vous utilisez simplement un opérateur de chaîne au lieu de l'opérateur regexp:
awk 'index($0,S1) && index($0.S2)'
Maintenant, que se passe-t-il si vous souhaitez faire correspondre 2 expressions rationnelles dans un paragraphe plutôt qu'une ligne? Ne peut pas être fait dans grep, trivial dans awk:
awk -v RS='' '/R1/ && /R2/'
Que diriez-vous de l'ensemble d'un fichier? Encore une fois, cela ne peut pas être fait en grep et trivial en awk (cette fois, j'utilise GNU awk pour RS multi-caractères pour la concision, mais ce n'est pas beaucoup plus de code dans n'importe quel awk ou vous pouvez choisir un contrôle-caractère que vous ne savez pas être en entrée pour que le RS fasse de même):
awk -v RS='^$' '/R1/ && /R2/'
Donc - si vous voulez trouver plusieurs expressions rationnelles ou chaînes dans une ligne ou un paragraphe ou un fichier, n'utilisez pas grep, utilisez awk.