sed手册明确指出替代字符串中替换字符串的可用反向引用编号为\ 1到\ 9。我正在尝试解析一个包含10个字段的日志文件。
我为它形成了正则表达式,但是第十场比赛(以及之后的任何内容)都无法访问。
有没有人有一种优雅的方法来规避KSH中的这种限制(或者我可以移植到shell脚本的任何语言)?
答案 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进行处理。