Regex 使用sed提取子串
我有以下内容的日志文件:Regex 使用sed提取子串,regex,linux,sed,Regex,Linux,Sed,我有以下内容的日志文件: example.com - - - 127.0.01 [22/Sep/2013:07:22:22 +0000] "POST /api/test.php HTTP/1.1" 200 355 "-" "-" "{\x22id\x22:\x22 ... }}}" example.com - - - 127.0.01 [22/Sep/2013:07:22:22 +0000] "POST /api/test.php HTTP/1.1" 200 355 "-" "-" "{\
example.com - - - 127.0.01 [22/Sep/2013:07:22:22 +0000] "POST /api/test.php HTTP/1.1" 200 355 "-" "-" "{\x22id\x22:\x22 ... }}}"
example.com - - - 127.0.01 [22/Sep/2013:07:22:22 +0000] "POST /api/test.php HTTP/1.1" 200 355 "-" "-" "{\x22id\x22:"{\x22 ... }}}"
我想将第一个{\x22
提取到最后一个}
因此,我使用以下sed命令:
cat test.txt | sed -r 's/.+?"(\{.+\})".*/\1/g'
然而,它给了我
{\x22id\x22:\x22 ... }}}
{\x22 ... }}}
但是我想要
{\x22id\x22:\x22 ... }}}
{\x22id\x22:"{\x22 ... }}}
因为它的正则表达式引擎不支持非贪婪匹配,所以
+?
不适用于sed
但是,如果考虑Perl,它是可能的:
perl -pe 's/.+?"(\{.+\})".*/\1/g' test.txt
{\x22id\x22:\x22 ... }}}
{\x22id\x22:"{\x22 ... }}}
或使用egrep-o
:
egrep -o '\{.+\}' test.txt
{\x22id\x22:\x22 ... }}}
{\x22id\x22:"{\x22 ... }}}
使用awk
awk '{sub(/[^{]*{/,"{");sub(/}"/,"}")}1' file
{\x22id\x22:\x22 ... }}}
{\x22id\x22:"{\x22 ... }}}
根据文本中要处理的内容,我使用变量剪切来更改任何其他“标记”。变量本身不需要,如果您确定剪切值不在文件中,您可以直接在sed中更改其内容,这可能对您有用(GNU sed):
贪婪在第一场比赛中是你的敌人,所以对{\x22
使用分而治之的习惯用法。即放置一个唯一的标记(在本例中为\n
),然后使用第二个替换命令删除字符串的第一部分。对于最后一个}
贪婪是你的朋友,因为*}
会自己找到最后一个匹配项
注意:如果第一个匹配是单个字符,比如说
X
,那么一个否定字符类[^X]*
就足够了。但是,由于它是一个字符串(两个或多个字符),这将不起作用。您也可以在激活perl引擎的情况下使用grepgrep-P
或pgrep
。然后,命令将是cat test.txt | grep-P-o”“
@ffledgeling:谢谢,更新后的答案是,yesegrep
也将与grep-P
的区别b/wegrep
或grep-E
相同,并且grep-P
是他们使用的正则表达式引擎egrep
是ERE
和pgrep
是Perl的引擎。虽然我从来没有看到过实际的差别。(注意pgrep和grep-P不一样,很抱歉混淆)
Cut="#CuT#"
sed -n --posix "s/\({\\\\x22.*}\)\"$/${Cut}\1/;s/.*${Cut}//p" sample.txt
sed 's/\({\\x22.*}\).*/\n\1/;s/.*\n//' file