我已经尝试过网络搜索,并且已经阅读了关于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
,因此相同的行提取也有效。
我想念什么?可以在一行命令中完成我想要的吗?
答案 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>(.*?)<Code
或Type>(.*)<Type
的出现。这给出了未命名分组表达式(?:Code>(.*?)<Code|Type>(.*?)<Type)
中交替的基本形式。 \b
确保关键字Code
和Type
匹配,但不匹配。 Code2
或TType
。 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>(.*?)<Code
和Type>(.*?)<Type
令牌的捕获可能是空字符串。这就是为什么我使用undef $c
和if 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