Comment donner un motif pour une nouvelle ligne dans grep?
95
Comment donner un motif pour une nouvelle ligne dans grep? Nouvelle ligne au début, nouvelle ligne à la fin. Pas la manière d'expression régulière. Quelque chose comme \ n.
Ce que vous voulez n'est pas clair. new line at the beginningest une ligne vide et new line at ends'applique à chaque ligne du fichier. Pouvez-vous poster un exemple?
PP
2
En fait, vous pouvez simplement utiliser $. C'est un peu limité, mais utilisable dans des cas simples.
grep les motifs sont comparés à des lignes individuelles, il n'y a donc aucun moyen pour un motif de correspondre à une nouvelle ligne trouvée dans l'entrée.
Cependant, vous pouvez trouver des lignes vides comme ceci:
grep '^$' file
grep '^[[:space:]]*$' file # include white spaces
Au moins GNU grep a l'option -z qui fait que grep coupe les lignes par un caractère nul. Cependant, il ne semble pas prendre en charge la nouvelle ligne ou \ n dans le modèle pour correspondre à la nouvelle ligne, voir rapport de bogue .
jarno
1
@jarno Il prend en charge \ n dans les modèles avec le drapeau -P
rubystallion
92
essayez pcregrepau lieu de régulier grep:
pcregrep -M "pattern1.*\n.*pattern2" filename
L' -Moption lui permet de correspondre sur plusieurs lignes, vous pouvez donc rechercher des nouvelles lignes en tant que \n.
-Pest une extension GNU. Je suis très bien pour l'utiliser lorsque la situation l'exige (généralement lookahead / lookbehind), mais POSIX grep peut le faire simplement avec [[:space:]].
jordanm
1
Les pages de manuel grep de FWIW, Solaris et BSD (sans vérifier les autres) ont toutes deux un paragraphe pour -P. GNU est de toute façon assez standard. :)
K3 --- rnc
1
Depuis la page de manuel: [-P] Cette option n'est pas prise en charge dans FreeBSD.
Grâce à @jarno, je connais l'option -z et j'ai découvert que lors de l'utilisation de GNU grep avec l'option -P, la correspondance avec \nest possible . :)
Super, notez que je ne reçois pas de notification concernant le "@jarno" dans la réponse.
jarno
3
C'est bien! Merci beaucoup d'avoir partagé!
Alicia Tang
6
En ce qui concerne la solution de contournement (sans utiliser de non portable -P), vous pouvez remplacer temporairement un caractère de nouvelle ligne par le différent et le modifier, par exemple:
grep -o "_foo_" <(paste -sd_ file) | tr -d '_'
Fondamentalement, il recherche une correspondance exacte _foo_où _signifie \n(so __= \n\n). Vous n'avez pas besoin de le traduire en arrière tr '_' '\n', car chaque motif serait imprimé dans la nouvelle ligne de toute façon, il _suffit donc de le supprimer .
pardonnez mon ignorance, mais l'utilisation de la substitution de processus n'est-elle pas encore une autre fonctionnalité compatible NON posix, donc non portable? dans le shell posix je ne pouvais pas faire <(p paste -sd_ file )?
humanityANDpeace
2
Viens juste de trouver
grep $'\r'
Il est utilisé $'\r'pour l'évasion de style C dans Bash.
new line at the beginning
est une ligne vide etnew line at end
s'applique à chaque ligne du fichier. Pouvez-vous poster un exemple?$
. C'est un peu limité, mais utilisable dans des cas simples.Réponses:
grep
les motifs sont comparés à des lignes individuelles, il n'y a donc aucun moyen pour un motif de correspondre à une nouvelle ligne trouvée dans l'entrée.Cependant, vous pouvez trouver des lignes vides comme ceci:
grep '^$' file grep '^[[:space:]]*$' file # include white spaces
la source
essayez
pcregrep
au lieu de réguliergrep
:pcregrep -M "pattern1.*\n.*pattern2" filename
L'
-M
option lui permet de correspondre sur plusieurs lignes, vous pouvez donc rechercher des nouvelles lignes en tant que\n
.la source
Vous pouvez utiliser cette façon ...
grep -P '^\s$' file
-P
est utilisé pour les expressions régulières Perl (une extension de POSIXgrep
).\s
correspond aux caractères d'espacement; s'il est suivi de*
, il correspond également à une ligne vide.^
correspond au début de la ligne.$
correspond à la fin de la ligne.la source
-P
est une extension GNU. Je suis très bien pour l'utiliser lorsque la situation l'exige (généralement lookahead / lookbehind), mais POSIX grep peut le faire simplement avec[[:space:]]
.-P
. GNU est de toute façon assez standard. :)brew install grep
obtenir GNU grep, qui est supérieur à plusieurs égards. apple.stackexchange.com/questions/193288/…Grâce à @jarno, je connais l'option -z et j'ai découvert que lors de l'utilisation de GNU grep avec l'option -P, la correspondance avec
\n
est possible . :)Exemple:
grep -zoP 'foo\n\K.*'<<<$'foo\nbar'
Tirages
bar
la source
En ce qui concerne la solution de contournement (sans utiliser de non portable
-P
), vous pouvez remplacer temporairement un caractère de nouvelle ligne par le différent et le modifier, par exemple:grep -o "_foo_" <(paste -sd_ file) | tr -d '_'
Fondamentalement, il recherche une correspondance exacte
_foo_
où_
signifie\n
(so__
=\n\n
). Vous n'avez pas besoin de le traduire en arrièretr '_' '\n'
, car chaque motif serait imprimé dans la nouvelle ligne de toute façon, il_
suffit donc de le supprimer .la source
<(p paste -sd_ file )
?Viens juste de trouver
grep $'\r'
Il est utilisé
$'\r'
pour l'évasion de style C dans Bash.dans cet article
la source