如何在下面給出的輸入文件中使用grep輸出字符串'export to excel'的出現?具體來說,如何處理搜索字符串之間發生的換行符? grep中是否有可以執行此操作或其他命令的開關?帶換行符的grep搜索字符串
輸入文件:
文件a.txt中:
等等等等......出口
Excel文檔...
等等等等..
文件B。 txt:
等等等等。 ...導出到Excel ...
等等等等..
如何在下面給出的輸入文件中使用grep輸出字符串'export to excel'的出現?具體來說,如何處理搜索字符串之間發生的換行符? grep中是否有可以執行此操作或其他命令的開關?帶換行符的grep搜索字符串
輸入文件:
文件a.txt中:
等等等等......出口
Excel文檔...
等等等等..
文件B。 txt:
等等等等。 ...導出到Excel ...
等等等等..
你只是想找到包含模式的文件,忽略換行符,或者你想真正看到匹配的行?
如果是前者,你可以使用tr
來換行轉換爲空格:
tr '\n' ' ' | grep 'export to excel'
如果你能做到同樣的事情後,但你可能需要使用-o標誌僅打印實際比賽。然後你需要調整你的正則表達式來包含你想要的任何額外的上下文。
tr + grep解決方案不適合大文件,因爲它將形成一個BIG字符串。 – ghostdog74 2009-12-07 08:47:25
使用gawk。將記錄分隔符設置爲excel,然後檢查「導出到」。
gawk -vRS="excel" '/export.*to/{print "found export to excel at record: "NR}' file
或
gawk '/export.*to.*excel/{print}
/export to/&&!/excel/{
s=$0
getline line
if (line~/excel/){
printf "%s\n%s\n",s,line
}
}' file
你會如何將實際的行打印爲'grep'(對於其能力範圍內的匹配)? – 2009-12-07 09:30:38
打印記錄,$ 0。否則,我不明白你的意思。 – ghostdog74 2009-12-07 12:40:58
我認爲你的編輯照顧。但是,它在某些邊緣情況下失敗。例如,如果輸入內容類似於「excel導出到\ nexcel」或「導出到\ nsomething以外的excel」。在你的評論中回答你的問題:如果在產出中增加了0美元,那麼最初的一行代碼將不會在OP的問題中指出後顯示「excel」,尤其是「...」。 – 2009-12-07 17:22:12
我已經測試這一點,似乎工作:
sed -n '$b; /export to excel/{p; b}; N; /export to\nexcel/{p; b}; D' filename
可以允許在年底開始的行的一些額外的空白區域和像這樣:
sed -n '$b; /export to excel/{p; b}; N; /export to\s*\n\s*excel/{p; b}; D' filename
我不知道如何在grep中做到這一點。我檢查了egrep(1)
的手冊頁,它也無法與中間的換行符匹配。
我喜歡解決方案@Laurence Gonsalves建議使用tr(1)
來消除換行符。但正如他所指出的,如果你這樣做,打印匹配線將會很痛苦。
如果你想匹配儘管換行符,然後打印匹配的行,我想不出一種方式來做到這一點與grep,但它不會太難在任何Python,AWK, Perl或Ruby。
這是一個解決問題的Python腳本。我決定,對於只有在加入前一行時才匹配的線條,我會在比賽的第二行之前打印一個-->
箭頭。完全匹配的行總是打印而沒有箭頭。
這是假設/ usr/bin/python是Python 2.x.如果需要,您可以簡單地將腳本更改爲在Python 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])
編輯:添加評論。
我遇到了一些麻煩,使它在每行上打印出正確的行號,使用的格式與grep -Hn
相似。
這可能是更短,更簡單,如果你不需要的行號,你不介意在整個文件一次讀入內存:
#!/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])
我看不到你用re.MULTILINE編譯正則表達式,那麼它如何檢查另一行上的「excel」? – ghostdog74 2009-12-07 12:45:43
re.MULTILINE是*不是*我想要的,所以我沒有指定它。使用re.MULTILINE,'re'代碼會像字符串的末尾那樣處理換行符,並且在之後不匹配。我想要一個換行符像匹配中的任何其他空白處理。我會在代碼中添加一些註釋。 – steveha 2009-12-07 15:59:35
其實,我的第一個版本可以在有或沒有re.MULTILINE的情況下工作。第二,slurp在整個文件版本不需要那個標誌,因爲它取決於匹配一個換行符。第一個版本創建一個特殊的單行,並剝離過程中的任何換行符。 – steveha 2009-12-07 16:18:22
據我所知(參考:Unix Power Tools)grep系列程序是面向行的,一次只讀一行,因此無法跨行查找模式。所以你可以考慮一個Perl腳本或在這裏使用sed。 HTH。 – sateesh 2009-12-07 07:29:16
如何在這種情況下使用sed? – 2009-12-07 07:55:16
@Vijay:echo -e「foo \ nbar」| sed -n'N;/foo \ nbar/p' – SiegeX 2009-12-07 08:42:18