我有很多文件,我需要从中获取信息。
我的档案示例:
第一个文件内容:
"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”但我无法通过使用相同的命令从第二个文件中获取信息。
请帮助重写命令或写另一个命令。
答案 0 :(得分:5)
我使用pcregrep
,它可以匹配多行正则表达式:
pcregrep -Mo 'test \K((?s).)*?(?=</singleline>)' filename
技巧是:
-M
允许pcregrep
匹配多行,-o
使其仅打印匹配项\K
扔掉了之前的比赛部分,(?=</singleline>)
是一个前瞻术语,匹配空字符串if(且仅当)后跟</singleline>
和((?s).)*?
非贪婪地匹配任何字符,也就是说如果文件中出现多次</singleline>
,它将匹配到最近而不是最远。如果不需要,请删除?
。 (?s)
在本地启用s
选项,使.
匹配其中的换行符;默认情况下它不会这样做。感谢@CasimiretHippolyte指出((?s).)
替代(.|\n)
。
答案 1 :(得分:2)
看起来你正在解析引用可打印的编码文本,其中一个“软”换行符(一个是固定行宽格式的伪像)用一行终止=
表示(直接在\n
之前。
因为在之后的评论中你也表达了将每个比赛打印成一行的愿望,我建议使用以下2-pass appraoch:
awk
删除软换行符grep
awk '/=$/ { printf "%s", substr($0, 1, length($0)-2); next } 1' file |
grep -Po 'test .*?(?=</singleline>)'
对于非贪婪量词的Wintermute's helpful answer的提示,*?
以及Wintermute和Maroun Maroun's helpful answer的正向前瞻断言,{{1} }。
不是(?=...)
命令删除行结尾awk
(以及换行符);仅使用=
替换substr
来电,以保留它。
由于感兴趣的字符串首先被转换回原始的单行表示:
$0
进行逐行匹配;与之形成对比
grep
必须在其答案中替换为*
才能在多个匹配的文件中正常工作。 *?
,如Wintermute's helpful answer。