Imprimer uniquement la sortie après avoir trouvé le motif

13

Il y a un script (appelons-le echoer) qui imprime pour filtrer un tas d'informations. J'aimerais pouvoir voir uniquement les lignes après avoir trouvé un motif.

J'imagine l'utilisation d'une solution pour ressembler à quelque chose

echoer | solution_command <pattern>

Idéalement, ce patternserait une expression régulière, mais des chaînes de valeur dures seraient suffisantes pour moi.

user23146
la source
Le motif peut donc être composé de plusieurs chaînes?
Inian
Un glob? Voulez-vous dire une expression régulière? Les globes n'ont de sens que pour les extensions de nom de fichier.
terdon
@Inian, je ne suis pas sûr de comprendre la question. Voulez-vous demander si je veux que cela fonctionne avec des disjonctions?
user23146

Réponses:

21

AWK peut le faire avec des plages de modèles, ce qui permet d'utiliser n'importe quelle expression régulière:

echoer | awk '/pattern/,0'

imprimera echoerla sortie en commençant par la première ligne correspondante pattern.

AWK est basé sur un modèle et est généralement utilisé avec une approche «si ce modèle correspond, faites cela». «Ce modèle» peut être une gamme de modèles, définie comme «lorsque ce modèle correspond, commencez à le faire, jusqu'à ce que cet autre modèle corresponde»; ceci est spécifié en écrivant deux modèles séparés par une virgule, comme ci-dessus. Les modèles peuvent être des correspondances de texte, comme dans /pattern/, où la ligne actuelle est vérifiée par rapport au modèle, interprétée comme une expression régulière; elles peuvent également être des expressions générales, évaluées pour chaque ligne et considérées comme identiques si leur résultat est non nul ou non vide.

Dans AWK, l'action par défaut consiste à imprimer la ligne actuelle.

En rassemblant tout cela, il awk '/pattern/,0'recherche les lignes correspondantes patternet une fois qu'il en trouve une, il applique l'action par défaut à toutes les lignes jusqu'à ce que la 0condition corresponde (non différente de zéro). awk '/pattern/,""'fonctionnerait aussi.

Le manuel de Gawk est beaucoup plus détaillé.

Stephen Kitt
la source
3
Je n'étais pas au courant de la sémantique de la plage avec zéro comme fin de la plage. Merci!
Kusalananda
@StephenKitt C'est super! Et si je voulais imprimer jusqu'à ce qu'il corresponde 0? Serait-ce /pattern/,/0/? À quoi ressemblerait la réponse en écrivant explicitement l'action par défaut?
user23146
@ user23146 oui, /pattern/,/0/s'imprime jusqu'à ce qu'il trouve une ligne (enregistrement) contenant "0". L'écriture de l'extrait dans la réponse avec une action explicite donne /pattern/,0 { print $0 }, ou de manière équivalente /pattern/,0 { print }.
Stephen Kitt
7

L' sedéquivalent obligatoire de celui de @ StephenKitt awk:

sed '/pattern/,$!d'

patternil est interprété comme une expression régulière de base comme dans grep(par opposition à l' expression régulière étendue dans awk/ egrep/ grep -E). Certaines sedimplémentations ont une option -E(BSD, ast, GNU / busybox récente, bientôt POSIX) ou -r(GNU, ssed, busybox, certains BSD récents) pour en faire des expressions régulières étendues à la place et d'autres ont -P(ast) ou -R(ssed) pour le faire une expression régulière de type perl.

Avec perl:

perl -ne 'print if /pattern/ .. undef'
Stéphane Chazelas
la source
4

avec GNU et * BSD grep:

grep -A1000000000 pattern file

À moins que votre fichier ne comporte plus de 1 million de lignes, c'est tout.

mosvy
la source
0

Si vous utilisez un téléavertisseur lesspour afficher la sortie de la commande

less +pattern
iruvar
la source
0

awk pour les lignes après (mais sans inclure) la première correspondance de motif

Si la ligne contenant le motif de déclenchement est l'équivalent de "COUPER ICI", vous pouvez l'omettre de la sortie imprimée:

echoer | awk 'flag ; /pattern/ { flag=1 }'

Chaque ligne d'entrée passe par deux composants dans le code awk. Le premier composant est flag, ce que awk interprète comme "affiche la ligne si la variable flagn'est pas nulle". Puisque les variables awk sont 0 par défaut, cela n'imprimera initialement rien.

Le deuxième composant /pattern/ { flag=1 },, définit l'indicateur à 1 dès qu'il détecte le modèle, et l'indicateur conserve cette valeur pour le reste de l'analyse.

Au moment où le motif est détecté pour la première fois, la possibilité d'imprimer cette ligne d'entrée est passée. Toutes les lignes suivantes (y compris les lignes supplémentaires contenant le motif) s'impriment.

Gaultheria
la source
0

Frapper

Un peu maladroit, mais ça marche.

#!/bin/bash
found=false
while IFS= read -r; do
    if $found || [[ $REPLY =~ pattern ]]; then
        found=true
        printf '%s\n' "$REPLY"
    fi
done

Cette version repose sur cat, mais elle est plus facile à comprendre.

#!/bin/bash
while IFS= read -r; do
    if [[ $REPLY =~ pattern ]]; then
        printf '%s\n' "$REPLY"
        break
    fi
done
cat
wjandrea
la source