Non so come farlo in grep. Ho controllato la pagina man per egrep(1)
e non può corrispondere con una nuova riga nel mezzo.
Mi piace la soluzione suggerita da Laurence Gonsalves, di utilizzare tr(1)
per eliminare le nuove righe. Ma come ha notato, sarà un problema stampare le righe corrispondenti se lo fai in questo modo.
Se si vuole uguagliare nonostante una nuova riga e quindi stampare la/e linea/e corrispondente/i, non riesco a pensare a un modo per farlo con grep, ma non sarebbe troppo difficile in nessuno dei Python, AWK, Perl o Ruby.
Ecco uno script Python che risolve il problema. Ho deciso che, per le linee che corrispondono solo se collegate alla riga precedente, stamperei una freccia -->
prima della seconda riga della partita. Le linee che si adattano a titolo definitivo vengono sempre stampate senza la freccia.
Questo è scritto supponendo che/usr/bin/python sia Python 2.x.È possibile cambiare banalmente lo script in modo che funzioni in Python 3.x se lo si desidera.
#!/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])
MODIFICA: commenti aggiunti.
Sono andato a qualche problema per farlo stampare il numero di linea corretto su ogni riga, utilizzando un formato simile a quello che si otterrebbe con grep -Hn
.
Potrebbe essere molto più breve e più semplice se non hai bisogno di numeri di riga, e non ti dispiace la lettura in tutto il file in una sola volta nella memoria:
#!/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])
Come ho capito (riferimento: Unix Power Tools) la famiglia di programmi grep è orientata alla linea, legge una riga alla volta e quindi non riesce a trovare pattern su tutta la linea. Quindi puoi pensare a uno script perl o usare sed qui. HTH. – sateesh
come usare sed in questo contesto? –
@Vijay: echo -e "pippo \ nbar" | sed -n 'N;/foo \ nbar/p' – SiegeX