我有一个测试文件,其中的数据如下:
00:00:00 [3.7.1.1] : referer [query: *:*] [filter: []] [warn: false]
xyx [cyx] word word [data [idd] is] [new data [x:r]] dd
xyx [111] word word [22 [3]] [1 bbb [x3:r]] ff
我希望有一个如下的输出结果,即返回方括号下的所有数据,并将嵌套的括号视为字符串,并保留其间的空格:
[3.7.1.1] [query: *:*] [filter: []] [warn: false]
[cyx] [data [idd] is] [new data [x:r]]
[111] [22 [3]] [1 bbb [x3:r]]
为了实现这一点,我使用了以下语句,但它不起作用:
echo file.txt | sed 's/.*[([^]]*)].*/1/g'
但它只返回嵌套的结果。
[x:r]
[x3:r]
我在这里做错了什么?我是注册表达式的新手,所以任何帮助都会很有用。非常感谢。
sed
不是处理嵌套平衡结构的最佳工具,但使用perl
可以轻松做到这一点:
perl -pe 's/([(?:[^][]++|(?1))*])h?(*SKIP)(*F)|.//g' infile > outfile
请参阅regex演示。详细信息:
([(?:[^][]++|(?1))*])h?(*SKIP)(*F)
-在匹配的方括号和后面的可选水平空白之间匹配子字符串,并跳过匹配|
-或.
-匹配换行符以外的任何字符
在线观看演示:
s='00:00:00 [3.7.1.1] : referer [query: *:*] [filter: []] [warn: false]
xyx [cyx] word word [data [idd] is] [new data [x:r]] dd
xyx [111] word word [22 [3]] [1 bbb [x3:r]] ff'
perl -pe 's/([(?:[^][]++|(?1))*])h?(*SKIP)(*F)|.//g' <<< "$s"
输出:
[3.7.1.1] [query: *:*] [filter: []] [warn: false]
[cyx] [data [idd] is] [new data [x:r]]
[111] [22 [3]] [1 bbb [x3:r]]
与其尝试匹配括号外的所有内容并将其删除,不如尝试匹配括号内的所有内容,并仅返回这些内容(同样使用perl
;递归正则表达式允许这种平衡对匹配(:
$ perl -nE 'say join " ", m/[(?:[^][]*|(?0))*]/g' input.txt
[3.7.1.1] [query: *:*] [filter: []] [warn: false]
[cyx] [data [idd] is] [new data [x:r]]
[111] [22 [3]] [1 bbb [x3:r]]