规避 sed 反向引用限制 \1 到 \9

发布于 2024-10-05 15:21:28 字数 177 浏览 1 评论 0原文

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

我已经为其形成了正则表达式,但第十个匹配项(以及之后的任何内容)无法访问。

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

The sed manual clearly states that the available backreferences available for the replacement string in a substitute are numbered \1 through \9. I'm trying to parse a log file that has 10 fields.

I have the regex formed for it but the tenth match (and anything after) isn't accessible.

Does anyone have an elegant way to circumvent this limitation in KSH (or any language that perhaps I can port to shell scripting)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

吾家有女初长成 2024-10-12 15:21:28

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

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

Can you user perl -pe 's/(match)(str)/$2$1/g;' in place of sed? The way to circumvent the backreference limit is to use something other than sed.

Also, I suppose you could do your substitution in two steps, but I don't know your pattern so I can't help you out with how.

无语# 2024-10-12 15:21:28

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

Split the stream with -e, as long as the replaced elements are with in the group that you split them with. When I did a date split so I could re-org the date-time into a string of 14 digits, I had to split the stream up 3 times.

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

私藏温柔 2024-10-12 15:21:28

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

这样可以吗?

You're asking for a shell script solution - that means you're not limited to using just sed, correct? Most shells support arrays, so perhaps you can parse the line into a shell array variable? If need be, you could even parse the same line multiple times, extracting different bits of information on each pass.

Would that do?

终止放荡 2024-10-12 15:21:28

如果您有 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

添加 \10sed 中断,它被认为是\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

If you have GNU awk, You can do things with much more in control. For this you would be needing match(source,/regex/,array) construct.

Example:

Sample input for test:

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

sed works fine till \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 broke when \10 is added, it is considered is \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 to rescue when any back reference added more than 9 is added. Here 10th refrence is added:

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
夜吻♂芭芘 2024-10-12 15:21:28

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

Consider a solution that doesn't require the use of regular expression backreferences. For example, if you have a simple field delimiter, use split, or even use awk for your processing instead of perl.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文