现在我在 awk 中有一个这样的 str:
str = "a='abc',b=1,c='http://xxxx,http://yyyy,http://zzz'"
如何解析它以获得此结果:
(a abc)(b 1)(c http://xxxx,http://yyyy,http://zzz)
现在我仍然以如此丑陋的方式实现它:
result = ""
while (match(str, /[^=]*=('[^']*'|[^,]*),/) != 0) {
subs = substr(str, RSTART, RLENGTH)
str = substr(str, RSTART + RLENGTH, length(str) - RSTART - RLENGTH + 1)
split(subs, vec, "=")
gsub(/'/, "", vec[1])
gsub(/'/, "", vec[2])
if (substr(vec[2], length(vec[2]), 1) == ",") {
vec[2] = substr(vec[2], 0, length(vec[2]) - 1)
}
result = result"("vec[1]" "vec[2]")"
}
我想知道是否存在一些更优雅的方式。
最佳答案
使用 awk
这里的技巧是我们需要以不同的方式对待带引号的逗号和不带引号的逗号。可以按如下方式完成:
$ echo "$str" | awk -F"'" -v OFS="" '{for (i=1;i<=NF;i+=2) gsub(",", ")(", $i)} {gsub("=", " "); print "("$0")"}'
(a abc)(b 1)(c http://xxxx,http://yyyy,http://zzz)
它是如何工作的
-F"'" -v OFS=""
这将输入字段分隔符设置为单引号,并将输出分隔符设置为空字符串。
{for (i=1;i<=NF;i+=2) gsub(",", ")(", $i)}
这会将不带引号的逗号(奇数字段)替换为
)(
.偶数字段代表引用的字符串,它们在这里保持不变。
gsub("=", " ")
这用空格替换等号。
print "("$0")"
这会在开头和结尾添加括号并打印该行。
使用 sed
$ echo "$str" | sed -r ":a; s/^(([^']*'[^']*')*[^']*'[^,']*),/\1\n/; ta; s/,/)(/g; s/^/(/; s/$/)/; s/\n/,/g; s/'//g; s/=/ /g"
(a abc)(b 1)(c http://xxxx,http://yyyy,http://zzz)
它是如何工作的
首先,请记住 sed 逐行处理输入。这意味着,除非我们在其中放入一个换行符,否则 sed 模式空间中的任何行都不会包含换行符。
此命令的工作原理是将所有引用的逗号替换为换行符。然后添加 (
到行首,)
到行尾,并将剩余的逗号替换为 )(
。换行符更改回逗号。接下来,单引号被删除。最后,=
然后将符号替换为空格,我们就完成了。
我们可以通过逗号前面是否有奇数个或偶数个单引号来判断逗号是否被引号引起来。
更详细:
sed -r
这会使用扩展正则表达式启动 sed。
:a; s/^(([^']*'[^']*')*[^']*'[^,']*),/\1\n/; ta
这会将所有带引号的逗号转换为换行符。正则表达式
^(([^']*'[^']*')*[^']*'[^,']*)
从行首开始匹配任何奇数个单引号及其周围的文本,直到第一个逗号为止。替换命令s/^(([^']*'[^']*')*[^']*'[^']*),/\1\n/
因此用换行符\n
替换找到的第一个引号逗号。 .:a
是一个标签。ta
是一个测试:它分支回标签a
如果进行了替换。因此,可以根据需要进行多次替换,以将所有带引号的逗号替换为换行符。s/,/)(/g; s/^/(/; s/$/)/
这三个替换命令将括号放在我们想要的任何地方。
s/\n/,/g
现在我们在需要的地方有了括号,这会将我们添加回的换行符转换为逗号。
s/'//g
这会删除所有单引号。
s/=/ /g
这将用空格替换等号。
关于awk - 如何在awk中简单地将这个字符串解析为kv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30586764/