我有一个 json 文件文件.json像这样:
{
"abc": "123",
"def": 456,
"ghi": 789
}
我试图在 bash 终端中使用正则表达式获取所有键的值。
这是我尝试获取价值的方法ABC:
var=cat file.json
regex='(abc\":) \"(.+)\",'
[[ $var =~ $regex ]]
echo ${BASE_REMATCH[1]}
它不打印任何东西。我正在尝试获取/打印值ABCIE“123”
请注意,我无法使用 jq,因为它无法在我需要它的机器上使用,而且我也无法安装它。
答案1
你需要类似的东西:
var=$(cat file.json) || exit
regex='"abc"[[:space:]]*:[[:space:]]*"((\\.|[^"\\])*)"'
if [[ $var =~ $regex ]]; then
value=${BASH_REMATCH[1]}
printf '%s\n' "$value"
fi
但即便如此,您也需要解码 json 字符串才能获取实际值。例如,foo\"\nbar
应转换为foo"<newline>bar
和。\u0031\u0032\u0033
123
最好是使用合适的 json 解析器:
value=$(jq .abc < file.json)
value=$(PERL_UNICODE= json_xs -t none -e 'print $_->{abc}' < file.json)
value=$(perl -C -MJSON -0777 -ne 'print decode_json($_)->{abc}' file.json)
value=$(
python3 -c 'import sys, json; print(json.load(sys.stdin)["abc"])' < file.json
)
您的方法存在的问题是:
- 获取命令输出的语法是 或
$(cmd)
已弃用的`cmd`
.var=cat file.json
将尝试运行在其环境中传递的file.json
命令。var=cat
\"
在正则表达式中没有任何意义。它可能被认为是相同的,"
但不能保证。.+
尽可能多地匹配一个或多个字符,因此它将匹配s 和换行符,直到字符串中的"
最后一个。在这里,我们将其替换为零个或多个(而不是)"
的序列,后跟任何单个字符或除or之外的字符,因此它会运行到下一个未转义的。*
+
\
\
"
"
- 您的正则表达式中有两个捕获组,第一个捕获组是 匹配的
(abc\":)
,而您显然需要第二个捕获组(值)。 - 变量是
$BASH_REMATCH
, 不是$BASE_REMATCH
- 您不能用于
echo
输出任意数据。 - 至少在列表上下文中,参数扩展必须在 bash 中引用。
答案2
如果您的文件确实像您显示的那样简单(字符串值中没有任何特殊的 JSON 编码),我将只使用awk
:
$ awk '$1=="\"abc\":"{print $2}' file | tr -d '",'
123
甚至 GNU grep
:
$ grep -oP '"abc":\s*"?\K[^,]+' file | tr -d '",'
123
启用-P
PCRE 正则表达式,让我们\K
“忽略到目前为止匹配的所有内容”。使用\K
选项-o
(“仅打印行的匹配部分”)让我们可以使用某些东西来找到正确的匹配项,然后将其丢弃,以便它不包含在输出中。所以在这里,我们要查找字符串"abc":
,然后是 0 个或多个空白字符 ( \s*
),后跟 0 个或一个引号 ( "?
),我们丢弃到目前为止的所有内容,然后查找最长的非"
字符 ( [^"]+
)。
最后,tr
将删除任何"
或,
字符,留下不带引号的值。