Tôi không biết làm thế nào để làm điều này trong grep. Tôi đã kiểm tra trang người đàn ông cho egrep(1)
và nó không thể phù hợp với một dòng mới ở giữa.
Tôi thích giải pháp @Laurence Gonsalves đề xuất, sử dụng tr(1)
để xóa các dòng mới. Nhưng như ông đã lưu ý, nó sẽ là một nỗi đau để in các dòng phù hợp nếu bạn làm theo cách đó.
Nếu bạn muốn kết hợp mặc dù dòng mới và sau đó in (các) dòng phù hợp, tôi không thể nghĩ ra cách để làm điều đó với grep, nhưng nó sẽ không quá khó trong bất kỳ Python, AWK, Perl, hoặc Ruby.
Đây là tập lệnh Python giải quyết được sự cố. Tôi quyết định rằng, đối với các dòng chỉ khớp khi được nối với dòng trước đó, tôi sẽ in một mũi tên -->
trước dòng thứ hai của trận đấu. Các đường thẳng hoàn toàn luôn được in mà không có mũi tên.
Điều này được viết giả định rằng/usr/bin/python là Python 2.x.Bạn có thể thay đổi kích thước kịch bản để làm việc theo Python 3.x nếu muốn.
#!/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: thêm nhận xét.
Tôi đã gặp một số sự cố để làm cho nó in đúng số dòng trên mỗi dòng, sử dụng một định dạng tương tự như những gì bạn sẽ nhận được với grep -Hn
.
Nó có thể là ngắn hơn nhiều và đơn giản hơn nếu bạn không cần số dòng, và bạn không nhớ đọc trong toàn bộ tập tin cùng một lúc vào bộ nhớ:
#!/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])
Khi tôi hiểu (tham khảo: Unix Power Tools) grep, các chương trình được định hướng dòng, đọc một dòng tại một thời điểm và do đó không thể tìm thấy các mẫu trên dòng. Vì vậy, bạn có thể nghĩ về một kịch bản perl hoặc sử dụng sed ở đây. HTH. – sateesh
cách sử dụng sed trong ngữ cảnh này? –
@Vijay: echo -e "foo \ nbar" | sed -n 'N;/foo \ nbar/p' – SiegeX