如何使用grep在下面给出的输入文件中输出字符串'export to excel'的出现次数?具体来说,如何处理搜索字符串之间发生的换行符? grep中是否有可以执行此操作或其他命令的开关?
输入文件:
档案a.txt:
等等等等......出口到 excel ...
等等等等。
文件b.txt:
等等......出口到excel ...
等等等等。
答案 0 :(得分:6)
您是否只想查找包含该模式的文件,忽略换行符,或者您是否希望实际看到匹配的行?
如果是前者,您可以使用tr
将换行符转换为空格:
tr '\n' ' ' | grep 'export to excel'
如果后者你可以做同样的事情,但你可能想使用-o标志只打印实际匹配。然后,您需要调整正则表达式以包含所需的任何额外上下文。
答案 1 :(得分:2)
我不知道如何在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])
答案 2 :(得分:1)
grep -A1“导出到”filename | grep -B1“excel”
答案 3 :(得分:0)
使用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
答案 4 :(得分:0)
我对此进行了一些测试,似乎有效:
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