两个标签之间的Grep/Sed与多线

Ser*_*erg 2 regex linux bash sed

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

我的文件示例:

第一个文件内容:

"test This info i need grep</singleline>"

第二个文件内容(有两行):

"test This info=
 i need grep too</singleline>"
Run Code Online (Sandbox Code Playgroud)

在结果中我需要grep这个文本:从第一个文件 - "这个信息我需要grep"和第二个文件 - "这个信息=我也需要grep"

在第一个文件中我使用:

grep -o 'test .*</singleline>' * | sed -e 's/test \(.*\)<\/singleline>/\1/'
Run Code Online (Sandbox Code Playgroud)

并成功获取"此信息我需要grep"但我无法通过使用相同的命令从第二个文件中获取信息.

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

Mar*_*oun 6

或者,如果您坚持使用grep,您可以:

grep -Pzo 'test(\n|.)*(?=</singleline>)' test.txt 
Run Code Online (Sandbox Code Playgroud)

要了解每个标志的含义,请使用grep --help:

  • -P, - pel-regexp

    PATTERN是一个Perl正则表达式

  • -o, - 只匹配

    仅显示匹配PATTERN的线条的一部分

  • -z, - 空数据

    数据行以0字节结尾,而不是换行符


Win*_*ute 5

我用pcregrep,它可以匹配多行正则表达式:

pcregrep -Mo 'test \K((?s).)*?(?=</singleline>)' filename
Run Code Online (Sandbox Code Playgroud)

技巧是:

  • -M允许pcregrep匹配多行,
  • -o 使它只打印匹配,
  • \K 扔掉前面的比赛的一部分,
  • (?=</singleline>)是一个前瞻术语,它匹配一个空字符串if(并且仅当它)后跟</singleline>,和
  • ((?s).)*?非贪婪地匹配任何字符,也就是说,如果你</singleline>在文件中有多次出现,它将匹配到最近而不是最远.如果不需要,请删除?.(?s)s本地为该术语启用选项以使其中包含.匹配换行符; 默认情况下它不会这样做.

感谢@CasimiretHippolyte指出((?s).)替代方案(.|\n).

  • 你应该避免这种丑陋(和效率低)的构造`(.| \n)*?`更多是为posix引擎设计的(除了非贪婪的量词).例如,您可以用`([^ <]*)`或`((?s).*?)来替换它(如果您想允许其他尖括号). (3认同)