我对awk
和perl
都是新手,所以请耐心等待。
我有以下awk
脚本:
awk '/regex1/{p = 0;} /regex2/{p = 1;} p'
这基本上是打印从与regex2匹配的行开始的所有行,直到找到与regex1匹配的行。
示例:
regex1
regex2
line 1
line 2
regex1
regex2
regex1
输出:
regex2
line 1
line 2
regex2
是否可以使用perl
单行程来模拟这个?我知道我可以用保存在文件中的脚本来完成它。
编辑:
一个实际的例子:
2017年5月24日17:00:06,827 [INFO] 123456(Blah:Blah1)服务名称::单行内容
2017年5月24日17:00:06,828 [INFO] 567890(Blah:Blah1)服务名称::内容(可能跨越多行)
2017年5月24日17:00:06,829 [INFO] 123456(Blah:Blah2) 服务名称:多行内容。打印对象[ID1 = fac-adasd ID2 = 123231
ID3 = 123108状态=未知
代码= 530007 Dest = CA
]2017年5月24日17:00:06,830 [INFO] 123456(Blah:Blah1)服务名称::单行内容
2017年5月24日17:00:06,831 [INFO] 567890(Blah:Blah2)服务名称::内容(可跨越多行)
鉴于搜索键123456,我想提取以下内容:
2017年5月24日17:00:06,827 [INFO] 123456(Blah:Blah1)服务名称::单行内容
2017年5月24日17:00:06,829 [INFO] 123456(Blah:Blah2) 服务名称:多行内容。打印对象[ID1 = fac-adasd ID2 = 123231
ID3 = 123108状态=未知
代码= 530007 Dest = CA
]2017年5月24日17:00:06,830 [INFO] 123456(Blah:Blah1)服务名称::单行内容
以下awk脚本完成工作:
awk '/[0-9]{2}\s\w+\s[0-9]{4}/{n = 0} /123456/ {n =1}n' file
答案 0 :(得分:2)
perl -ne 'print if (/regex2/ .. /regex1/) =~ /^\d+$/'
这有点疯狂,但这是它的工作原理:
-n
在输入行上添加隐式循环$_
/regex2/
,/regex1
/)隐式测试$_
我们在标量上下文中使用..
,将其转换为有状态的触发器运算符
我的意思是:X .. Y
从“假”状态开始。在“错误”状态下,它仅评估X
。如果X
返回false值,则它将保持“false”状态(并自行返回false)。一旦X
返回一个真值,它就会进入“true”状态并返回true。
在“true”状态下,它仅评估Y
。如果Y
返回false,则它保持“true”状态(并返回true本身)。一旦Y
返回一个真值,它就会进入“假”状态但它仍然返回true。
如果我们刚刚使用print if /regex2/ .. /regex1/
,它也会打印所有终止regex1
行
perldoc perlop
表明您可以区分范围的终点..
返回的“true”值实际上是从1
开始的序列号,因此可以通过检查1
当达到范围的结尾时(即我们将要再次从“true”状态转移到“false”状态),返回值将被加"E0"
结束
将"E0"
添加到整数不会影响其数值。 Perl在需要时隐式地将字符串转换为数字,而"5E0"
之类的东西只是科学记数法(意为5 * 10**0
,即5 * 1
,即5
)。
..
返回的“false”值为空字符串""
我们检查..
的结果是否与正则表达式/^\d+$/
匹配,即是所有数字。这排除了空字符串(因为我们需要至少一个数字匹配),所以我们不打印范围之外的行。它也排除了我们范围内的最后一行,因为E
不是数字。
答案 1 :(得分:0)
不确定awk是否同时打印范围的开头和结尾,但Perl会:
perl -ne 'if(/regex2/ ... /regex1/){print}' file
编辑:Awk(至少Gnu awk)也有一个范围运算符,所以这可以更简单地完成:
awk '/regex2/,/regex1/' file