从不同行向后看的Perl提取组

时间:2019-04-05 14:50:30

标签: regex perl

我已经尝试过网络搜索,并且已经阅读了关于stackexchange的几个答案,但仍然无法理解为什么命令不提取任何内容。最后,我想从不同的行(例如来自

Code>TEST1<Code Code2>best<Code2
Code>test2<Code
Type>false<Type

通过在Type之间找到所需的键并在结果上方首先提取Code来提取test2。但是我无法成功地从多行中提取某些内容,即

perl -lne 'print $1,"_",$2 if /Code>(.*)<Code[\s\S\n]*?Type>(.*)<Type/'<test.txt不打印任何内容。
我玩过删除ln参数并添加/删除贪婪?并尝试仅用.代替[\s\S\n]的方法。

perl -lne 'print $1,"_",$2 if /Code>(.*)<Code[\s\S\n]*?Code2>(.*)<Code2/'<test.txt 给出TEST1_best,因此相同的行提取也有效。

我想念什么?可以在一行命令中完成我想要的吗?

3 个答案:

答案 0 :(得分:2)

以下命令回答了您的问题:如果它们后面跟着Code>...<Code模式(它们之间可能有其他模式,但没有其他出现的{ {1}}之间):

Type>...<Type

例如Code>...<Code包含以下几行,

perl -lne 's/^.*?(?=Code>)//s; for (split /Code>/) { print qq($1:$2\n) if /(.*?)<Code.*?Type>(.*?)<Type/s }' -0777 <test.txt

然后该命令将收集以下值对:

test.txt

于04/08/2019,17:38 CEST 编辑。我删除了文件“页眉部分”(第一次出现之前的部分)的命令。 (Code>test4<Code Type>false<Type Code>test3<Code Type>true<Type Code>TEST1<Code Code2>best<Code2 Code>test2<Code Type>false<Type )中的内容,由于文件编辑器的某些错误,它可能包含一个结束标记test4:false test3:true test2:false ,该标记没有用Code>打开,而是用例如<Code。我的假设是,完整文件是“语法上正确的”,因为它包含类型Code>的元素,并用空格分隔(包括换行符)。对于不符合此语法的文件,该语句不防水。

答案 1 :(得分:1)

使用渐进匹配和嵌入式代码的另一种方法

perl -lne 'while (/\b(?:Code>(.*?)<Code(?{$c=$1})|Type>(.*?)<Type(?{print qq($c:$2\n) if defined $c;undef $c}))\b/g){}' -0777 <test.txt

说明:

  • 基本上,该表达式查找Code>(.*?)<CodeType>(.*)<Type的出现。这给出了未命名分组表达式(?:Code>(.*?)<Code|Type>(.*?)<Type)中交替的基本形式。
  • 该组周围的单词边界声明\b确保关键字CodeType匹配,但不匹配。 Code2TType
  • 修饰符g确保在字符串上逐步应用正则表达式。由于我想在表达式本身内部提取结果,因此将正则表达式放在一个空循环中,即while (/.../g) {}
  • 您假设有一个语法规则Code ⟶ Type,即您查找在Type标记之后出现Code标记的情况。为此,将Code令牌存储在带有代码表达式$c的变量(?{$c=$1})中。如果找到了Type标记,则只有在以前找到了Code标记的情况下,它才被视为匹配项,这由定义了变量$c的事实指示。无论如何,如果找到了Type标记,则变量$c将被undef d为其准备下一次搜索。这样会在正则表达式的(${print qq($c:$2\n) if defined $c;undef $c;})分支中给出代码评估Type
  • 请注意,Code>(.*?)<CodeType>(.*?)<Type令牌的捕获可能是空字符串。这就是为什么我使用undef $cif defined $c而不是简单的$c=''if $c的原因。

答案 2 :(得分:0)

如果您的数据在“ d”中,则由gnu sed提供;

sed -Ez 's/.*Code>(\w+)<Code\sType>\w*<Type.*/\1/' d

Perl

perl -ne 'BEGIN{undef $/} /Code>(\w+)<Code\nType>\w*<Type/; print $1' d