我有很多文件,我需要从中获取信息。
我的文件示例:
第一个文件内容:
"test This info i need grep</singleline>"
和
第二个文件内容(两行):
"test This info= i need grep too</singleline>"
在结果我需要grep这个文本:从第一个文件 – “这个信息我需要grep”和从第二个文件 – “这个信息=我需要grep太”
在我使用的第一个文件中:
grep -o 'test .*</singleline>' * | sed -e 's/test \(.*\)<\/singleline>/\1/'
并成功地得到“这个信息我需要grep”,但我不能从第二个文件通过使用相同的命令获取信息。
请帮助改写命令或写另一个。
我会使用pcregrep
,它可以匹配多行的正则表达式:
pcregrep -Mo 'test \K((?s).)*?(?=</singleline>)' filename
这些技巧是:
-M
允许pcregrep
匹配多个行, -o
使它只打印匹配, \K
扔掉之前的比赛的一部分, (?=</singleline>)
是一个与空字符串匹配的前瞻性术语,如果(且仅当)后面紧跟</singleline>
,则 ((?s).)*?
以非贪婪的方式匹配任何字符,也就是说,如果文件中有多个</singleline>
出现,它将匹配到最近而不是最远。 如果不需要,请删除?
。 (?s)
在本地启用该选项.
匹配换行符; 它不会默认这样做。 感谢@CasimiretHippolyte指出((?s).)
替代(.|\n)
。
或者,如果你坚持使用grep
,你可以:
grep -Pzo 'test(\n|.)*(?=</singleline>)' test.txt
要理解每个标志的含义,请使用grep --help
:
-P
,–perl-regexp
PATTERN是一个Perl正则表达式
-o
, – 唯一匹配
仅显示匹配PATTERN的行的部分
-z
,–null-data
数据行以0字节结尾,而不是换行符
它看起来像解析quoted-printable编码文本,其中一个“软”换行符(一个是来自固定行宽格式化的工件)用line-terminating =
(直接在\n
之前)表示。
由于在稍后的评论中你也表达了打印每一场比赛的愿望,所以我建议以下两个方面的评价:
awk
删除软线断点 grep
awk '/=$/ { printf "%s", substr($0, 1, length($0)-2); next } 1' file | grep -Po 'test .*?(?=</singleline>)'
Wintermute对非贪婪量词的有用答案的提示, *?
,而Wintermute和Maroun Maroun对积极的预见性断言(?=...)
提供了有用的答案 。
不是说awk
命令删除行结尾=
(与新行一起); 用$0
替换substr
调用来保留它。
由于感兴趣的字符串首先被转换回原来的单行表示:
grep
逐行匹配; 与此形成对比
*
必须替换为*?
在他的工作正确工作的答案在多个匹配的文件。 pcregrep
,如Wintermute的有用答案 。