Je ne sais pas comment faire ça dans grep. J'ai vérifié la page man pour egrep(1)
et il ne peut pas non plus correspondre avec une nouvelle ligne dans le milieu. J'aime la solution proposée par @Laurence Gonsalves, d'utiliser tr(1)
pour effacer les retours à la ligne. Mais comme il l'a noté, il sera difficile d'imprimer les lignes correspondantes si vous le faites de cette façon.
Si vous voulez faire correspondre malgré un retour à la ligne et ensuite imprimer les lignes correspondantes, je ne peux pas penser à un moyen de le faire avec grep, mais ce ne serait pas trop difficile dans tout de Python, AWK, Perl, ou Ruby.
Voici un script Python qui résout le problème. J'ai décidé que, pour les lignes qui ne correspondent que lorsqu'elles sont jointes à la ligne précédente, j'imprimerais une flèche -->
avant la deuxième ligne du match. Les lignes qui correspondent parfaitement sont toujours imprimées sans la flèche.
Ceci est écrit en supposant que/usr/bin/python est Python 2.x.Vous pouvez modifier le script de manière triviale pour travailler sous Python 3.x si vous le souhaitez.
#!/usr/bin/python
import re
import sys
s_pat = "export\s+to\s+excel"
pat = re.compile(s_pat)
def print_ete(fname):
try:
f = open(fname, "rt")
except IOError:
sys.stderr.write('print_ete: unable to open file "%s"\n' % fname)
sys.exit(2)
prev_line = ""
i_last = -10
for i, line in enumerate(f):
# is ete within current line?
if pat.search(line):
print "%s:%d: %s" % (fname, i+1, line.strip())
i_last = i
else:
# construct extended line that included previous
# note newline is stripped
s = prev_line.strip("\n") + " " + line
# is ete within extended line?
if pat.search(s):
# matched ete in extended so want both lines printed
# did we print prev line?
if not i_last == (i - 1):
# no so print it now
print "%s:%d: %s" % (fname, i, prev_line.strip())
# print cur line with special marker
print "--> %s:%d: %s" % (fname, i+1, line.strip())
i_last = i
# make sure we don't match ete twice
prev_line = re.sub(pat, "", line)
try:
if sys.argv[1] in ("-h", "--help"):
raise IndexError # print help
except IndexError:
sys.stderr.write("print_ete <filename>\n")
sys.stderr.write('grep-like tool to print lines matching "%s"\n' %
"export to excel")
sys.exit(1)
print_ete(sys.argv[1])
EDIT: commentaires ajoutés.
J'ai eu des problèmes pour imprimer le bon numéro de ligne sur chaque ligne, en utilisant un format similaire à celui que vous obtiendriez avec grep -Hn
.
Il pourrait être beaucoup plus court et plus simple si vous n'avez pas besoin des numéros de ligne, et vous ne faites pas attention à lire dans le fichier entier à la fois dans la mémoire:
#!/usr/bin/python
import re
import sys
# This pattern not compiled with re.MULTILINE on purpose.
# We *want* the \s pattern to match a newline here so it can
# match across multiple lines.
# Note the match group that gathers text around ete pattern uses a character
# class that matches anything but "\n", to grab text around ete.
s_pat = "([^\n]*export\s+to\s+excel[^\n]*)"
pat = re.compile(s_pat)
def print_ete(fname):
try:
text = open(fname, "rt").read()
except IOError:
sys.stderr.write('print_ete: unable to open file "%s"\n' % fname)
sys.exit(2)
for s_match in re.findall(pat, text):
print s_match
try:
if sys.argv[1] in ("-h", "--help"):
raise IndexError # print help
except IndexError:
sys.stderr.write("print_ete <filename>\n")
sys.stderr.write('grep-like tool to print lines matching "%s"\n' %
"export to excel")
sys.exit(1)
print_ete(sys.argv[1])
Si je comprends bien (référence: Unix Power Tools) famille de programmes grep sont orientés ligne, lire une ligne à la fois et ne peut donc pas trouver des modèles à travers la ligne. Vous pouvez donc penser à un script Perl ou utiliser Sed ici. HTH. – sateesh
comment utiliser Sed dans ce contexte? –
@Vijay: echo -e "foo \ nbar" | sed -n 'N;/foo \ nbar/p' – SiegeX