Grep cherchant deux mots dans une ligne

39

J'ai essayé de trouver un moyen de filtrer une ligne contenant le mot "citron" et "riz". Je sais comment trouver "citron" ou "riz" mais pas les deux. Ils n'ont pas besoin d'être à côté de l'autre, juste une même ligne de texte.

    
posée Sebastian 26.02.2015 - 22:13
la source

6 réponses

51

"Les deux sur la même ligne" signifie "riz" suivi de caractères aléatoires suivis de "citron" ou inversement ".

Dans regex qui est rice.*lemon ou lemon.*rice . Vous pouvez combiner cela en utilisant | :

grep -E 'rice.*lemon|lemon.*rice' some_file

Si vous souhaitez utiliser une expression régulière au lieu d'une expression étendue ( -E ), vous avez besoin d'une barre oblique inverse avant | :

grep 'rice.*lemon\|lemon.*rice' some_file

Pour plus de mots qui deviennent rapidement un peu longs et qu'il est généralement plus facile d'utiliser plusieurs appels de grep , par exemple:

grep rice some_file | grep lemon | grep chicken
    
réponse donnée Florian Diesch 26.02.2015 - 22:29
la source
23

Vous pouvez diriger la sortie de la première commande grep vers une autre commande grep qui correspondrait aux deux modèles. Donc, vous pouvez faire quelque chose comme:

grep <first_pattern> <file_name> | grep <second_pattern>

ou,

cat <file_name> | grep <first_pattern> | grep <second_pattern>

Exemple:

Ajoutons du contenu à notre fichier:

$ echo "This line contains lemon." > test_grep.txt
$ echo "This line contains rice." >> test_grep.txt
$ echo "This line contains both lemon and rice." >> test_grep.txt
$ echo "This line doesn't contain any of them." >> test_grep.txt
$ echo "This line also contains both rice and lemon." >> test_grep.txt

Que contient le fichier:

$ cat test_grep.txt 
This line contains lemon.
This line contains rice.
This line contains both lemon and rice.
This line doesn't contain any of them.
This line also contains both rice and lemon.

Maintenant, laissez-nous ce que nous voulons:

$ grep rice test_grep.txt | grep lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.

Nous n'obtenons que les lignes où les deux modèles correspondent. Vous pouvez étendre cela et diriger la sortie vers une autre commande grep pour d'autres correspondances "AND".

    
réponse donnée Aditya 26.02.2015 - 22:31
la source
17

Bien que la question demande "grep", j'ai pensé qu'il pourrait être utile de poster une solution simple "awk":

awk '/lemon/ && /rice/'

Cela peut facilement être étendu avec plus de mots, ou d’autres expressions booléennes en plus de «et».

    
réponse donnée David B. 27.02.2015 - 04:49
la source
10

Une autre idée pour trouver les correspondances dans n'importe quel ordre utilise:

grep avec l'option -P (Perl-Compatibility) et regex de recherche positive (?=(regex)) :

grep -P '(?=.*?lemon)(?=.*?rice)' infile

ou vous pouvez utiliser ci-dessous, à la place:

grep -P '(?=.*?rice)(?=.*?lemon)' infile
  • Le .*? signifie que tous les caractères . apparaissant à zéro ou plus fois * sont facultatifs, suivis d'un motif ( rice ou lemon ). Le ? rend tout facultatif avant (signifie zéro ou une fois tout correspondant à .* )

(?=pattern) : Positive Lookahead: La construction positive est une paire de parenthèses, la parenthèse ouvrante étant suivie d'un point d'interrogation et d'un signe égal.

Cela retournera donc toutes les lignes contenant à la fois lemon et rice dans un ordre aléatoire. Cela évitera également d’utiliser | s et de doubler grep s.

Liens externes:
Thèmes avancés de Grep
Recherche positive - GREP pour les concepteurs

    
réponse donnée αғsнιη 27.02.2015 - 00:05
la source
2
grep -e foo -e goo

Renverra les correspondances pour foo ou goo

    
réponse donnée netskink 24.07.2017 - 16:46
la source
0

Voici un script pour automatiser la solution de tuyauterie grep:

#!/bin/bash

# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}

grepand () {
# disable word splitting and globbing
IFS=
set -f
if [[ -n  ]]
then
grep -i "" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}

grepand "[email protected]"
    
réponse donnée Jeff 03.02.2017 - 02:21
la source

Lire d'autres questions sur les étiquettes