Comment tronquer les longues lignes correspondantes renvoyées par grep ou ack

90

Je veux exécuter ack ou grep sur des fichiers HTML qui ont souvent de très longues lignes. Je ne veux pas voir de très longues lignes qui s'enroulent à plusieurs reprises. Mais je veux voir juste cette partie d'une longue ligne qui entoure une chaîne qui correspond à l'expression régulière. Comment puis-je obtenir cela en utilisant n'importe quelle combinaison d'outils Unix?

dan
la source
1
Quoi ack? Est-ce une commande que vous utilisez lorsque vous n'aimez pas quelque chose? Quelque chose comme ack file_with_long_lines | grep pattern? :-)
Alok Singhal
6
@Alok ack(connu sous ack-greple nom de Debian) est grepsous stéroïdes. Il a également l' --thppptoption (sans blague). betterthangrep.com
ZoogieZork
Merci. J'ai appris quelque chose aujourd'hui.
Alok Singhal
1
Alors que la --thppptfonction est quelque peu controversée, l'avantage clé semble être que vous pouvez utiliser Perl Regexes directement, pas un fou [[:space:]]et des personnages comme {, [, etc. En changeant le sens avec le -eet les -Ecommutateurs d'une manière qui est impossible de se souvenir.
Evgeni Sergeev

Réponses:

99

Vous pouvez utiliser l'option grep -o, éventuellement en combinaison avec le changement de votre modèle ".{0,10}<original pattern>.{0,10}"afin de voir un contexte autour de lui:

       -o, --only-matching
              Afficher uniquement la partie d'une ligne correspondante qui correspond à PATTERN.

..ou -c:

       -c, --count
              Supprimer la sortie normale; à la place, imprimez un nombre de lignes correspondantes
              pour chaque fichier d'entrée. Avec l'option -v, --invert-match (voir
              ci-dessous), comptez les lignes non correspondantes.
Éther
la source
44
un exemple: grep -oE ". {0,20} mysearchstring. {0,20}" myfile
Renaud
14
vous devriez changer la réponse pour ajouter l'option -E comme indiqué par @Renaud (option de modèle étendu), ou le modèle proposé pour étendre le contexte ne fonctionnera pas.
kriss
Pas si nécessaire peut-être, mais voici un exemple: $ echo "eeeeeeeeeeeeeeeeeeeeqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrrrr" > fileonelongline.txt && grep -oE ".{0,20}MYSTRING.{0,20}" ./fileonelongline.txt tiragesqqqqqqqqqqqqqqqqqqqqMYSTRINGwwwwwwwwwwwwwwwwwwww
Ulises Layera
Cela fonctionne bien; mais l'inconvénient notable est que lors de l'utilisation, par exemple, oE ".{0,20}mysearchstring.{0,20}"vous perdez la mise en évidence de la chaîne "originale" interne par rapport au contexte, car l'ensemble devient le modèle de recherche. J'adorerais trouver un moyen de conserver un contexte non mis en évidence autour des résultats de la recherche, pour une analyse visuelle et une interprétation des résultats beaucoup plus faciles.
Aaron Wallentine
1
Oh, voici une solution au problème de mise en évidence causé par l'utilisation de l' -oE ".{0,x}foo.{0,x}"approche (où xest le nombre de caractères du contexte) - append `| grep foo `jusqu'à la fin. Fonctionne pour les solutions ack ou grep. Plus de solutions également ici: unix.stackexchange.com/questions/163726/…
Aaron Wallentine
44

Transmettez vos résultats cut. J'envisage également d'ajouter un --cutcommutateur pour que vous puissiez dire --cut=80et n'obtenir que 80 colonnes.

Andy Lester
la source
8
Et si la partie qui correspond ne figure pas dans les 80 premiers caractères?
Ether
3
FWIW j'ai ajouté | cut=c1-120au grep, a travaillé pour moi (mais je ne sais pas comment couper le texte correspondant)
Jake Rayson
26
| cut=c1-120n'a pas fonctionné pour moi, j'avais besoin de le faire| cut -c1-120
Ken Cochrane
1
Je pense que @edib est précis dans la syntaxe | cut -c 1-100 stackoverflow.com/a/48954102/1815624
CrandellWS
1
@AndyLester: Qu'en est-il d'une --no-wrapoption qui utilise $COLUMNS?
naught101
25

Vous pouvez utiliser less comme téléavertisseur pour ack et hacher les longues lignes: ack --pager="less -S" Cela conserve la longue ligne mais la laisse sur une seule ligne au lieu de l'enrouler. Pour voir plus de la ligne, faites défiler vers la gauche / droite en moins avec les touches fléchées.

J'ai la configuration d'alias suivante pour ack pour ce faire:

alias ick='ack -i --pager="less -R -S"' 
Jonah Braun
la source
2
Veuillez noter que vous pouvez mettre cette --pagercommande dans votre fichier ~ / .ackrc, si vous souhaitez toujours l'utiliser.
Andy Lester
Cela semble être de loin la meilleure solution à ce problème qui me dérange beaucoup. J'aurais aimé savoir comment m'en servir ack.
Brian Peterson
@BrianPeterson ackest à peu près comme grep, mais plus simple dans les cas les plus courants
Aaron Wallentine
8
cut -c 1-100

obtient des caractères de 1 à 100.

edib
la source
2

Tiré de: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/

L'approche suggérée ".{0,10}<original pattern>.{0,10}"est parfaitement bonne sauf que la couleur de surbrillance est souvent foirée. J'ai créé un script avec une sortie similaire mais la couleur est également préservée:

#!/bin/bash

# Usage:
#   grepl PATTERN [FILE]

# how many characters around the searching keyword should be shown?
context_length=10

# What is the length of the control character for the color before and after the
# matching string?
# This is mostly determined by the environmental variable GREP_COLORS.
control_length_before=$(($(echo a | grep --color=always a | cut -d a -f '1' | wc -c)-1))
control_length_after=$(($(echo a | grep --color=always a | cut -d a -f '2' | wc -c)-1))

grep -E --color=always "$1" $2 |
grep --color=none -oE \
    ".{0,$(($control_length_before + $context_length))}$1.{0,$(($control_length_after + $context_length))}"

En supposant que le script est enregistré sous grepl, alors grepl pattern file_with_long_linesdevrait afficher les lignes correspondantes mais avec seulement 10 caractères autour de la chaîne correspondante.

xuhdev
la source
Fonctionne, mais génère des fichiers indésirables pour moi, comme ceci: ^ [[? 62; 9; c. Je n'ai pas essayé le débogage parce que la réponse de @Jonah Braun m'a satisfait.
sondra.kinsey
1

Voici ce que je fais:

function grep () {
  tput rmam;
  command grep "$@";
  tput smam;
}

Dans mon .bash_profile, je remplace grep pour qu'il s'exécute automatiquement tput rmamavant et tput smamaprès, ce qui a désactivé l'encapsulation, puis le réactive.

ognockocatène
la source
C'est une bonne alternative - sauf si le match réel est alors hors de l'écran ...
Xerus
1

entrez la description de l'image ici

Dans la situation inhabituelle où vous ne pouvez pas utiliser -E, vous pouvez utiliser:

grep -oe ".\{0,10\}error.\{0,10\}" mylogfile.txt
Josh Withee
la source
0

J'ai mis ce qui suit dans mon .bashrc:

grepl() {
    $(which grep) --color=always $@ | less -RS
}

Vous pouvez ensuite utiliser greplsur la ligne de commande tous les arguments disponibles pour grep. Utilisez les touches fléchées pour voir la queue des lignes plus longues. Utilisez qpour quitter.

Explication:

  • grepl() {: Définissez une nouvelle fonction qui sera disponible dans chaque (nouvelle) console bash.
  • $(which grep): Obtenez le chemin complet de grep. (Ubuntu définit un alias pour grepcela équivaut à grep --color=auto. Nous ne voulons pas de cet alias mais de l'original grep.)
  • --color=always: Colorisez la sortie. (à --color=autopartir de l'alias ne fonctionnera pas car grepdétecte que la sortie est placée dans un tube et ne la colorera pas ensuite.)
  • $@: Mettez ici tous les arguments donnés à la greplfonction.
  • less: Afficher les lignes en utilisant less
  • -R: Afficher les couleurs
  • S: Ne cassez pas les longues lignes
pt1
la source