绕过sed反向引用限制\ 1到\ 9

时间:2010-11-30 20:15:42

标签: regex shell sed backreference

sed手册明确指出替代字符串中替换字符串的可用反向引用编号为\ 1到\ 9。我正在尝试解析一个包含10个字段的日志文件。

我为它形成了正则表达式,但是第十场比赛(以及之后的任何内容)都无法访问。

有没有人有一种优雅的方法来规避KSH中的这种限制(或者我可以移植到shell脚本的任何语言)?

5 个答案:

答案 0 :(得分:13)

您可以使用perl -pe 's/(match)(str)/$2$1/g;'代替sed吗?规避反向引用限制的方法是使用除sed之外的其他内容。

另外,我想你可以分两步进行替换,但我不知道你的模式,所以我无法帮你解决问题。

答案 1 :(得分:5)

使用-e拆分流,只要替换的元素与您拆分的组合在一起即可。当我进行日期分割以便将日期时间重新组合成14位数的字符串时,我不得不将流分割3次。

echo "created: 02/05/2013 16:14:49" |  sed -e 's/^\([[:alpha:]]*: \)//' -e 's/\([0-9]\{2\}\)\(\/\)\([0-9]\{2\}\)\(\/\)\([0-9]\{4\}\)\( \)/\5\1\3/' -e 's/\([0-9]\{2\}\)\(\:\)\([0-9]\{2\}\)\(\:\)\([0-9]\{2\}\)/\1\3\5/'

20130205161449

答案 2 :(得分:3)

你要求一个shell脚本解决方案 - 这意味着你不仅限于使用sed,对吗?大多数shell支持数组,所以也许你可以将该行解析为shell数组变量?如果需要,你甚至可以多次解析同一行,在每次传递中提取不同的信息。

那会吗?

答案 3 :(得分:2)

如果你有GNU awk,你可以用更多的东西来控制。为此,您需要match(source,/regex/,array)构造。

示例:

测试样本输入:

 echo "$x"
p1=aaa,p2=bb,p3=cc,p4=dd,p5=ee,p6=ff,p7=gg,p8=hh,p9=ii,p10=jj

sed工作正常,直到\9

echo $x |sed -r 's/p1=([^,]+).*p2=([^,]+).*p3=([^,]+).*p4=([^,]+).*p5=([^,]+).*p6=([^,]+).*p7=([^,]+).*p8=([^,]+).*p9=([^,]+)(.*)/\1 \2 \3 \4 \5 \6 \7 \8 \9/'
aaa bb cc dd ee ff gg hh ii
添加sed后,

\10内爆,被视为\1 + 0

echo $x |sed -r 's/p1=([^,]+).*p2=([^,]+).*p3=([^,]+).*p4=([^,]+).*p5=([^,]+).*p6=([^,]+).*p7=([^,]+).*p8=([^,]+).*p9=([^,]+).*p10=([^,]+)(.*)/\1 \2 \3 \4 \5 \6 \7 \8 \9 \10/'
aaa bb cc dd ee ff gg hh ii aaa0
添加超过9的后向引用时,

awk进行救援。这里增加了第10次参考:

echo "$x" |awk '{match($0,/p1=([^,]+).*p2=([^,]+).*p3=([^,]+).*p4=([^,]+).*p5=([^,]+).*p6=([^,]+).*p7=([^,]+).*p8=([^,]+).*p9=([^,]+).*p10=([^,]+)(.*)/,a);print a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10]}'
aaa bb cc dd ee ff gg hh ii jj

答案 4 :(得分:1)

考虑一个不需要使用正则表达式反向引用的解决方案。例如,如果您有一个简单的字段分隔符,请使用split,甚至使用awk代替perl进行处理。