使用sed提取子字符串

时间:2013-11-14 07:08:15

标签: 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 "-" "-" "{\x22id\x22:"{\x22 ... }}}"

我想将第一个{\x22提取到最后}

所以我使用以下sed命令:

cat test.txt  | sed -r  's/.+?"(\{.+\})".*/\1/g'

然而,它给了我

{\x22id\x22:\x22 ... }}}

{\x22 ... }}}

但我想要

{\x22id\x22:\x22 ... }}}

{\x22id\x22:"{\x22 ... }}}

4 个答案:

答案 0 :(得分:0)

.+?不能与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 ... }}}

答案 1 :(得分:0)

使用awk

awk '{sub(/[^{]*{/,"{");sub(/}"/,"}")}1' file
{\x22id\x22:\x22 ... }}}

{\x22id\x22:"{\x22 ... }}}

答案 2 :(得分:0)

Cut="#CuT#"
sed -n --posix "s/\({\\\\x22.*}\)\"$/${Cut}\1/;s/.*${Cut}//p" sample.txt

我使用变量Cut来改变任何其他"标记"取决于要处理的文本内容。如果你确定Cut的值不在文件中,你可以直接在sed中更改它的内容

答案 3 :(得分:0)

这可能适合你(GNU sed):

sed 's/\({\\x22.*}\).*/\n\1/;s/.*\n//' file

贪婪是你在第一场比赛中的敌人所以使用分而治之的习惯用于{\x22。这是一个唯一的标记(在本例中为\n)并使用第二个替换命令来删除字符串的第一部分。对于最后一次}贪婪,你的朋友.*}将自己找到最后一场比赛。

N.B。如果第一个匹配是单个字符,比如说X,那么否定的字符类[^X]*就足够了。但是因为它是一个字符串(两个或多个字符),所以这不起作用。