Je dois parcourir certains fichiers JSON dans lesquels la longueur des lignes dépasse quelques milliers de caractères. Comment puis-je limiter grep pour afficher le contexte jusqu'à N caractères à gauche et à droite de la correspondance? Tout outil autre que grep conviendrait également, tant qu'il est disponible dans les packages Linux courants.
Ce serait un exemple de sortie, pour le commutateur grep imaginaire Ф :
$ grep -r foo *
hello.txt: Once upon a time a big foo came out of the woods.
$ grep -Ф 10 -r foo *
hello.txt: ime a big foo came of t
Réponses:
Avec GNU
grep
:Explication:
-o
=> N'imprimer que ce que vous avez assorti-P
=> Utiliser des expressions régulières de style Perl$N
caractèresfoo
suivi de 0 par les$N
caractères.Si vous n'avez pas GNU
grep
:Explication:
Comme nous ne pouvons plus compter sur
grep
GNUgrep
, nous utilisonsfind
pour rechercher des fichiers de manière récursive (l'-r
action de GNUgrep
). Pour chaque fichier trouvé, nous exécutons l'extrait de code Perl.Commutateurs Perl:
-n
Lire le fichier ligne par ligne-l
Retirez la nouvelle ligne à la fin de chaque ligne et remettez-la lors de l'impression-e
Traitez la chaîne suivante comme du codeL'extrait de code Perl fait essentiellement la même chose que
grep
. Il commence par définir une variable$N
sur le nombre de caractères de contexte que vous souhaitez. LesBEGIN{}
moyens ceci est exécuté qu'une seule fois au début de l' exécution pas une seule fois pour chaque ligne dans chaque fichier.L'instruction exécutée pour chaque ligne consiste à imprimer la ligne si la substitution d'expression régulière fonctionne.
Le regex:
^.*?
) suivi par.{0,$N}
comme dans legrep
cas, suivi parfoo
suivi d'une autre.{0,$N}
et finalement faites correspondre n'importe quelle vieille chose paresseusement jusqu'à la fin de la ligne (.*?$
).$ARGV:$1
.$ARGV
est une variable magique qui contient le nom du fichier en cours de lecture.$1
est ce que les parens correspondaient: le contexte dans ce cas.foo
sans échouer (car elle.{0,$N}
est autorisée à correspondre à zéro fois).1 Autrement dit, préférez ne rien faire correspondre sauf si cela entraînerait l'échec de la correspondance globale. En bref, faites correspondre le moins de caractères possible.
la source
| grep foo
à la fin (mais en perdant la mise en surbrillance du nom de fichier dans le processus).grep
vous pouvez spécifier les couleurs / applications de correspondance en fonction des indicateurs appliqués via les variables d'environnement. alors peut-être même que vous pourriez les gagner tous (pas de promesses - même pas sûr que cela fonctionnerait dans ce cas) mais je ne vois pas personnellement la pertinence ici ... de toute façon ... continuez à jouer.zsh
Je ne peux pas le faire fonctionner en passant N = 10 comme dans l'exemple. Cependant, cela fonctionne si jeexport N=10
avant d'exécuter la commande. Une idée comment ajuster l'exemple pour travailler avec zsh?perl -lne 'print "$ARGV: $_" for /.{0,10}foo.{0,10}/g'
Essayez d'utiliser celui-ci:
-E indique que vous souhaitez utiliser l'expression régulière étendue
-o indique que vous ne souhaitez imprimer que la correspondance
-r grep recherche le résultat récursivement dans le dossier
REGEX:
{0,10} indique le nombre de caractères arbitraires que vous souhaitez imprimer
. représente un caractère arbitraire (un caractère lui-même n'était pas important ici, juste leur nombre)
Edit: Oh, je vois, que Joseph recommande presque la même solution que moi: D
la source
-E
est beaucoup plus rapide que-P
.Tiré de: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ et https: // stackoverflow. com / a / 39029954/1150462
L'approche suggérée
".{0,10}<original pattern>.{0,10}"
est parfaitement bonne, sauf que la couleur de surbrillance est souvent gâchée. J'ai créé un script avec une sortie similaire mais la couleur est également préservée:En supposant que le script est enregistré sous
grepl
, ilgrepl pattern file_with_long_lines
devrait afficher les lignes correspondantes, mais avec seulement 10 caractères autour de la chaîne correspondante.la source
Passe-partout
cut
avec le-b
drapeau; vous pouvez indiquer à la sortie de grep uniquement les octets 1 à 400 par ligne.la source