J'ai un fichier avec environ 1000 lignes. Je veux la partie de mon fichier après la ligne qui correspond à mon instruction grep.
C'est:
$ cat file | grep 'TERMINATE' # It is found on line 534
Donc, je veux le fichier de la ligne 535 à la ligne 1000 pour un traitement ultérieur.
Comment puis je faire ça?
grep 'TERMINATE' file
grep
interface d'entrée standard pour lire les données, plutôt que d'avoir à apprendre à quel commutateur appliquergrep
, etsed
, etawk
, etpandoc
,ffmpeg
etc. lorsque nous voulons lire à partir d'un fichier. Cela fait gagner du temps car nous n'avons pas à apprendre un nouveau commutateur à chaque fois que nous voulons faire la même chose: lire à partir d'un fichier.grep 'TERMINATE' < file
. Peut-être que cela rend la lecture un peu plus difficile - mais c'est du script shell, donc ça va toujours être un problème :)Réponses:
Ce qui suit imprimera la ligne correspondant
TERMINATE
jusqu'à la fin du fichier:Expliqué:
-n
désactive le comportement par défautsed
de l'impression de chaque ligne après avoir exécuté son script dessus, a-e
indiqué un script àsed
,/TERMINATE/,$
est une sélection de plage d'adresses (ligne) signifiant la première ligne correspondant à l'TERMINATE
expression régulière (comme grep) à la fin du fichier ($
) , etp
est la commande d'impression qui imprime la ligne courante.Cela imprimera à partir de la ligne qui suit la ligne correspondant
TERMINATE
jusqu'à la fin du fichier:(d'Après la ligne correspondante à EOF, sans inclure la ligne correspondante)
Expliqué:
1,/TERMINATE/
est une sélection de plage d'adresses (ligne) signifiant la première ligne pour l'entrée de la 1ère ligne correspondant à l'TERMINATE
expression régulière, etd
est la commande de suppression qui supprime la ligne actuelle et passe à la ligne suivante. Lesed
comportement par défaut étant d'imprimer les lignes, il imprimera les lignes aprèsTERMINATE
la fin de l'entrée.Éditer:
Si vous voulez les lignes avant
TERMINATE
:Et si vous voulez les deux lignes avant et après
TERMINATE
dans 2 fichiers différents en un seul passage:Les fichiers avant et après contiendront la ligne avec terminate, donc pour traiter chacun d'entre eux, vous devez utiliser:
Edit2:
SI vous ne souhaitez pas coder en dur les noms de fichiers dans le script sed, vous pouvez:
Mais alors vous devez échapper à la
$
signification de la dernière ligne pour que le shell n'essaie pas de développer la$w
variable (notez que nous utilisons maintenant des guillemets doubles autour du script au lieu de guillemets simples).J'ai oublié de dire que la nouvelle ligne est importante après les noms de fichiers dans le script afin que sed sache que les noms de fichiers se terminent.
Edit: 2016-0530
Sébastien Clément a demandé: "Comment remplaceriez-vous le codé
TERMINATE
en dur par une variable?"Vous créeriez une variable pour le texte correspondant, puis vous le feriez de la même manière que dans l'exemple précédent:
pour utiliser une variable pour le texte correspondant aux exemples précédents:
Les points importants sur le remplacement du texte par des variables dans ces cas sont:
$variablename
) entresingle quotes
['
] ne "se développeront" pas mais les variables à l'intérieur dedouble quotes
["
] le seront. Donc, vous devez changer tous lessingle quotes
endouble quotes
s'ils contiennent du texte que vous souhaitez remplacer par une variable.sed
gammes contiennent également$
et sont immédiatement suivies d'une lettre comme:$p
,$d
,$w
. Ils examineront également comme des variables à être étendu, donc vous devez échapper à ces$
personnages avec une barre oblique inverse [\
] comme:\$p
,\$d
,\$w
.la source
sed -e "1,/$matchtext/d"
ne fonctionne pas lorsqu'il$matchtext
se produit dans la première ligne. J'ai dû le changer ensed -e "0,/$matchtext/d"
.Comme simple approximation, vous pouvez utiliser
qui greps pour
TERMINATE
et produit jusqu'à 100 000 lignes suivant cette ligne.Depuis la page de manuel
la source
file
:grep -A$(cat file | wc -l) TERMINATE file
Un outil à utiliser ici est awk:
Comment cela marche-t-il:
Les autres solutions peuvent consommer beaucoup de mémoire si vous les utilisez sur des fichiers très volumineux.
la source
cat file | awk 'BEGIN{ found=0} /###/{found=found+1} {if (found<2) print }'
cat
.awk
est parfaitement capable de prendre un ou plusieurs noms de fichiers comme arguments. Voir aussi stackoverflow.com/questions/11710552/useless-use-of-catSi je comprends bien votre question, vous voulez les lignes après
TERMINATE
, sans compter laTERMINATE
ligne.awk
peut le faire d'une manière simple:Explication:
if(found) print
) n'imprimera rien pour commencer.Cela imprimera toutes les lignes après la
TERMINATE
ligne.Généralisation:
Exemple:
Explication:
found
est défini.found=1
sorte que les lignes suivantes soient imprimées. Notez que cette vérification est effectuée après l'impression réelle d'exclure le début -ligne du résultat.Remarques:
BEGIN{found=0}
au début de l'expression awk.la source
{if(found) print}
c'est un peu un anti-pattern dans awk, il est plus idiomatique de remplacer le bloc par justefound
oufound;
si vous avez besoin d'un autre filtre par la suite.awk '{if(found) print} /TERMINATE/{found=1}' your_file
parawk 'found; /TERMINATE/{found=1}' your_file
, ils devraient tous les deux faire la même chose.Utilisez l'expansion des paramètres bash comme suit:
la source
printf
ou vous assurer de savoir exactement à quoi vous passezecho
.).grep -A 10000000 fichier 'TERMINATE'
la source
Il existe de nombreuses façons de le faire avec
sed
ouawk
:Cela recherche
TERMINATE
dans votre fichier et imprime à partir de cette ligne jusqu'à la fin du fichier.C'est exactement le même comportement que
sed
.Si vous connaissez le numéro de la ligne à partir de laquelle vous souhaitez démarrer l'impression, vous pouvez le spécifier avec
NR
(numéro d'enregistrement, qui indique éventuellement le numéro de la ligne):Exemple
la source
more +7 file
Si pour une raison quelconque, vous souhaitez éviter d'utiliser sed, ce qui suit affichera la ligne correspondant
TERMINATE
jusqu'à la fin du fichier:et ce qui suit sera imprimé à partir de la ligne suivante correspondant
TERMINATE
jusqu'à la fin du fichier:Il faut 2 processus pour faire ce que sed peut faire en un seul processus, et si le fichier change entre l'exécution de grep et tail, le résultat peut être incohérent, je recommande donc d'utiliser sed. De plus, si le fichier ne contient pas
TERMINATE
, la 1ère commande échoue.la source
Alternatives à l'excellente
sed
réponse de jfgagne, et qui n'incluent pas la ligne correspondante:awk '/TERMINATE/ {y=1;next} y'
( https://stackoverflow.com/a/18166628 )awk '/TERMINATE/ ? c++ : c'
( https://stackoverflow.com/a/23984891 )perl -ne 'print unless 1 .. /TERMINATE/'
( https://stackoverflow.com/a/18167194 )la source
Cela pourrait être une façon de procéder. Si vous savez quelle ligne du fichier vous avez votre mot grep et combien de lignes vous avez dans votre fichier:
grep -A466 fichier 'TERMINATE'
la source
grep
n'est même pas nécessaire; vous pouvez simplement utilisertail -n $NUM
, donc ce n'est pas vraiment une réponse.sed est un bien meilleur outil pour le travail: fichier sed -n '/ re /, $ p'
où re est l'expression rationnelle.
Une autre option est l'indicateur --after-context de grep. Vous devez passer un nombre pour terminer à, l'utilisation de wc sur le fichier devrait donner la bonne valeur pour s'arrêter. Combinez cela avec -n et votre expression de correspondance.
la source
Ceux-ci imprimeront toutes les lignes de la dernière ligne trouvée "TERMINATE" jusqu'à la fin du fichier:
la source
grep
pour pouvoir le nourrirtail
est un anti-modèle inutile. La recherche de la correspondance et l'impression jusqu'à la fin du fichier (ou, au contraire, l'impression et l'arrêt à la première correspondance) se font éminemment avec les outils de regex normaux et essentiels eux-mêmes. Le massifgrep | tail | sed | awk
est également en soi une utilisation inutile etgrep
massive d' amis .tail
et faites la tâche dans l'outil le plus performant. Quoi qu'il en soit, le titre dit clairement "premier match".