【发布时间】:2013-12-19 14:25:34
【问题描述】:
我有一个命令,其输出格式为:
[{"foo1":<some value>,"foo2":<some value>,"foo3":<some value>}]
我想获取这个命令的输出,只获取foo2对应的值
如何使用 sed/awk 或 bash 脚本中随时可用的任何其他 shell 实用程序来执行此操作?
【问题讨论】:
-
你有不同的“:
”内容的样本来定义可能的分隔符
我有一个命令,其输出格式为:
[{"foo1":<some value>,"foo2":<some value>,"foo3":<some value>}]
我想获取这个命令的输出,只获取foo2对应的值
如何使用 sed/awk 或 bash 脚本中随时可用的任何其他 shell 实用程序来执行此操作?
【问题讨论】:
假设值不包含逗号,这个sed rune 会这样做:
sed -n 's/.*"foo2":\([^,]*\),.*/\1/'p
sed -n 告诉sed 默认不打印行。
s ("substitute") 命令使用由\( 和\) 分隔的正则表达式组来挑选您想要的位。
"foo2": 提供找到正确值所需的上下文。
[^,]* 表示“一个不是逗号的字符,任意次数”。这是你的 。如果值没有用逗号分隔,请更改它(以及分组括号后的逗号)以正确匹配。
.* 表示“任意字符,任意次数”,用于匹配你想要的位前后的所有字符。现在正则表达式将匹配整行。
\1 表示分组括号的内容。 sed 将用括号的内容替换与模式匹配的字符串(这是整行,因为我们在开头和结尾使用了 .*)。
最后,末尾的p 表示“打印结果行”。
【讨论】:
以awk 为例:
$ awk -F[:,] '{print $4}' file
<some value2>
-F[:,] 将可能的字段分隔符设置为 : 或 ,。然后,就是计算foo2 的<some value> 所在位置的问题。正好是第四个。sed:
$ sed 's/.*"foo2":\([^,]*\).*/\1/g' file
<some value2>
.*"foo2":\([^,]*\).* 获取 foo2: 之后的字符串,直到逗号出现。然后它用\1 打印回来。【讨论】:
awk 版本是真的。由于我们没有更多的样本数据,我假设没有。但是,sed 解决方案应该可以正确解决。
您的数据块看起来像 JSON。 bash、sed 或 awk 中没有原生 JSON 解析,所以这里的所有答案要么建议你使用不同的、更合适的工具,要么它们会很老套,如果你的真实数据很容易失败看起来与您在此处提供的示例不同。
也就是说,如果您确信您的 variable:value 块和行结构始终采用与本示例相同的格式,您也许可以自己编写(非常)仅适用于您的用例的基本解析器。
请注意,您不能真正解析 sed 中的内容,它只是不是为此而设计的。如果您的数据看起来总是相同,则 sed 解决方案可能就足够了……但请记住,您只是模式匹配,而不是解析输入数据。已经有其他答案涵盖了这一点。
对于出现在"foo2" 之后的冒号之后的字符串的非常简单的匹配,正如彼得建议的那样,您可以使用以下内容:
$ data='[{"foo1":11,"foo2":222,"foo3":3333}]'
$ echo "$data" | sed -ne 's/.*"foo2":\([^,]*\),.*/\1/p'
正如我所说,这绝不应该与您的 JSON 的 解析 相混淆。对于abcde"foo2":bar,abcde 的输入字符串,它同样适用(或很差)。
在 awk 中,您可以制作更高级的东西,但在 JSON 方面仍然存在严重限制。例如,如果您选择用逗号分隔字段,但随后在数据中的 <some value> 中放置了一个逗号,则 awk 不知道如何将其与字段分隔符区分开来。
也就是说,如果您的 JSON 只有一层深度(即与您的示例数据匹配),那么以下方法可能适合您:
$ data='[{"foo1":11,"foo2":222,"foo3":3333}]'
$ echo "$data" | awk -F: -vRS=, '{gsub(/[^[:alnum:]]/,"",$1)} $1=="foo2" {print $2}'
此 awk 脚本将逗号视为记录分隔符,将冒号视为字段分隔符。它不支持 JSON 中的任何深度级别,并且取决于字母数字变量名称。但它应该处理 JSON 拆分为多行。
或者,如果您想避免丑陋的 hack,而 perl 或 python 解决方案不适合您,您可能想尝试 jsawk。有了它,你可能会使用这样的东西:
$ data='[{"foo1":11,"foo2":222,"foo3":3333}]'
$ echo "$data" | jsawk -a 'return this.foo2'
[222]
另请参阅:Parsing json with awk/sed in bash to get key value pair
【讨论】:
这对我有用。你可以试试这个
echo "[{"foo1":<some value>,"foo2":<some value>,"foo3":<some value>}]" | awk -F"[:,]+" '{ if($3=="foo2") { print $4 }}'
上面的 awk 使用了多个字段分隔符。我在这里使用了冒号和逗号
【讨论】:
因为这看起来像 JSON,让我们像 JSON 一样解析它:
perl -MJSON -ne '$json = decode_json($_); print $json->[0]{foo2}, "\n"' <<END
[{"foo1":"some value","foo2":"some, value","foo3":"some value"}]
END
some, value
【讨论】: