具有多行

时间:2015-05-09 13:02:50

标签: regex linux bash sed

我有很多文件,我需要从中获取信息。

我的档案示例:

第一个文件内容:

"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”但我无法通过使用相同的命令从第二个文件中获取信息。

请帮助重写命令或写另一个命令。

2 个答案:

答案 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来电,以保留它。

由于感兴趣的字符串首先被转换回原始的单行表示:

  • 比赛以原始形式打印。
  • 您可以使用常规(GNU)$0进行逐行匹配;与之形成对比
    • 需要立即读取整个文件 ,如Maroun Maroun's helpful answer 请注意,在撰写本文时,grep必须在其答案中替换为*才能在多个匹配的文件中正常工作。
    • 需要安装另一个实用程序*?,如Wintermute's helpful answer
    • 此外,必须将匹配清理为单行(您最初未将其作为要求)。