如何以简单的方式将此字符串解析为awk中的kv

时间:2015-06-02 03:22:04

标签: awk

现在我有一个像这样的str:

"chockkors ~0.1"

如何解析它以获得此结果:

str = "a='abc',b=1,c='http://xxxx,http://yyyy,http://zzz'"

到现在为止,我仍然以如此丑陋的方式实现它:

(a abc)(b 1)(c http://xxxx,http://yyyy,http://zzz)

我想知道是否存在更优雅的方式。

1 个答案:

答案 0 :(得分: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")"

    这会在开头和结尾添加parens并打印该行。

使用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/$/)/

    这三个替换命令将parens放在我们想要的任何地方。

  • s/\n/,/g

    现在我们需要它们的parens,这会将我们添加的换行符转换回逗号。

  • s/'//g

    这会删除所有单引号。

  • s/=/ /g

    用空格替换等号。