Nie wiem, jak to zrobić w grep. Sprawdziłem stronę man dla egrep(1)
i nie może ona być zgodna z nowym znakiem w środku.
Podoba mi się rozwiązanie @Laurence Gonsalves zasugerował, aby użyć tr(1)
do usunięcia nowych linii. Ale jak zauważył, będzie to trudny wydruk pasujących linii, jeśli zrobisz to w ten sposób.
Jeśli chcesz dopasować pomimo nowego wiersza, a następnie wydrukować pasujące wiersze, nie mogę wymyślić sposobu, aby to zrobić z grep, ale nie byłoby to zbyt trudne w żadnym z Python, AWK, Perl lub Ruby.
Oto skrypt w języku Python, który rozwiązuje problem. Zdecydowałem, że w przypadku linii, które pasują tylko po połączeniu z poprzednią linią, wydrukowałbym strzałkę -->
przed drugą linią meczu. Linie, które pasują wprost, są zawsze drukowane bez strzałki.
Zostało to napisane przy założeniu, że/usr/bin/python to Python 2.x.W razie potrzeby możesz w trywialny sposób zmienić skrypt tak, by działał w Pythonie 3.x.
#!/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])
EDYCJA: dodano komentarze.
Poszedłem do kłopotów, aby wydrukować prawidłowy numer linii w każdym wierszu, używając formatu podobnego do tego, co otrzymasz z grep -Hn
.
To może być dużo krótsza i prostsza, jeśli nie trzeba numery linii, i nie przeszkadza w czytaniu całego pliku od razu do pamięci:
#!/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])
Jak rozumiem (referencje: Unix Power Tools) rodzina programów grep jest zorientowana liniowo, czyta linię po linii i dlatego nie może znaleźć wzorów wzdłuż linii. Więc możesz wymyślić skrypt perla lub użyć sed tutaj. HTH. – sateesh
jak korzystać z sed w tym kontekście? –
@Vijay: echo -e "foo \ nbar" | sed -n 'N;/foo \ nbar/p' – SiegeX