18

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

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

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

4

5 回答 5

15

你可以用用户perl -pe 's/(match)(str)/$2$1/g;'代替 sed 吗?绕过反向引用限制的方法是使用 sed 以外的东西。

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

于 2010-11-30T20:19:44.940 回答
6

使用 -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

于 2013-06-18T16:31:36.630 回答
3

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

会这样吗?

于 2010-11-30T20:19:42.897 回答
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

awk当添加超过 9 的任何反向引用时进行救援。这里添加了第 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
于 2017-03-29T09:10:02.983 回答
1

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

于 2013-02-26T23:39:26.187 回答