2012-01-24 4 views
3

Est-il possible de faire apparaître grep un nombre maximum de mots avant et après le match? Par exemple, étant donné la ligneGrep: max mots avant et après le match

aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm nnn ooo ppp qqq rrr sss 

Je voudrais grep ne pas revenir ligne entière, mais seulement, disons, 3 mots avant et après le match. par exemple, la recherche de « iii », le résultat serait

fff ggg hhh iii jjj kkk lll 

J'ai essayé cela, mais ne renvoie aucun résultat:

grep -o '\w{0, 20}MY_SEARCH\w{0, 20}' * 
+0

Pouvez-vous s'il vous plaît donner des précisions sur votre question de ce que vous avez l'intention de faire? –

+0

Je ne pense pas que 'grep' puisse le faire. Vous devrez peut-être écrire un petit script comme ceci 'awk '{pour (i = 1; i <= NF; i ++) if ($ i ==" iii ") {pour (k = i-3; k <= i + 3; k ++) printf ("% s", $ k)} print ""} 'filename' –

+0

J'ai modifié le message avec un nouveau script..Vérifiez cela – Raghuram

Répondre

0

J'ai essayé de convertir les espaces pour les nouvelles lignes, puis utilisez - A et -B option, puis reconvertir \ n à l'espace.

$ echo "aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm nnn ooo ppp qqq rrr sss" | tr ' ' '\n' | grep -A3 -B3 "iii" | tr '\n' ' ' 

op => fff ggg hhh iii jjj kkk lll

Je sais que une approche brute, mais besoin de vérifier toute autre meilleure option est présente.

J'ai écrit un petit script shell avec cette logique pour gérer plusieurs fichiers. Cochez cette

#!/bin/bash 

for i in `find . -name "*.txt"` 
do 
    FNAME=$i 
    MATCHED="" 
    if grep "iii" $i > /dev/null 2>&1 
    then 
     MATCHED=`cat $i | tr ' ' '\n' | grep -A3 -B3 "iii" | tr '\n' ' '` 
    fi 

    if [ "$MATCHED" != "" ] 
    then 
     echo "$FNAME|$MATCHED" 
    fi 
done  
+0

merci, cela peut fonctionner, mais cela fonctionnera-t-il lorsque la sortie n'est pas une seule ligne mais '*' et donc l'appliquer à plusieurs fichiers? – pistacchio

+0

depuis que je joue avec \ n, j'ai besoin d'essayer – Raghuram

+0

@pistacchio Le 'one-liner 'awk posté dans les commentaires peut parcourir plusieurs fichiers. Bien que cela dépende de la taille du fichier, il se peut qu'il ne soit pas aussi efficace. –

2
string='aaa bbb ccc ddd eee fff ggg hhh iii jjj kkk lll mmm nnn ooo ppp qqq rrr sss' 

echo $string | grep -oP '(([a-zA-Z]+)){0,3}iii(([a-zA-Z]+)){0,3}' 

Si je comprends bien compris votre question, cela devrait le faire lorsque le nombre maximum de mots de chaque côté sont 3.

0
grep -E -o '.{0, 3}iii.{0, 3}' 

il sortira ce

hhh iii jjj 

si vous voulez supprimer 'iii', vous pouvez également piquer un sed

grep -E -o '.{0,3}iii.{0,3}' | sed 's/iii//g' 

il sortira ce

hhh jjj