我正在尝试使用Python从某些JSON中提取信息(在我无法安装jq的系统上)。我当前的方法与Why can't use semi-colon before for loop in Python?中描述的语法限制相冲突。如何根据此限制修改此代码仍然有效?
我目前的代码如下所示:
$ SHIFT=$(aws ec2 describe-images --region "$REGION" --filters "Name=tag:Release,Values=$RELEASE_CODE_1.2003.2")
$ echo "$SHIFT" | python -c "import sys, json; for image in json.load(sys.stdin)['Images']: print image['ImageId'];"
File "<string>", line 1
import sys, json; for image in json.load(sys.stdin)['Images']: print image['ImageId'];
^
SyntaxError: invalid syntax
由于Python的语法不允许将for
循环与带分号的先前命令分开,我如何解决此限制?
答案 0 :(得分:4)
这里有几个选项:
将您的代码作为多行字符串传递。请注意,为简单起见,"
用于分隔Python字符串而不是原始'
:POSIX兼容机制,用于在单引号字符串中嵌入文字'
{ {3}}
extractImageIds() {
python -c '
import sys, json
for image in json.load(sys.stdin)["Images"]:
print image["ImageId"]
' "$@"
}
使用bash的C样式转义字符串语法($''
)来嵌入换行符,与$'\n'
一样。请注意,前导$
至关重要,而且这不适用于/bin/sh
。有关详细信息,请参阅is possible, but quite ugly。
extractImageIds() { python -c $'import sys, json\nfor image in json.load(sys.stdin)["Images"]:\n\tprint image["ImageId"]' "$@"; }
使用the bash-hackers' wiki on ANSI C-like strings可以避免需要单独的import
命令。
extractImageIds() { python -c 'for image in __import__("json").load(__import__("sys").stdin)["Images"]: print image["ImageId"]' "$@"; }
传递stdin上的代码并将输入移动到argv;请注意,这仅在输入不会超出操作系统允许的最大命令行大小时才有效。请考虑以下示例:
extractImageIds() {
# capture function's input to a variable
local input=$(</dev/stdin) || return
# ...and expand that variable on the Python interpreter's command line
python - "$input" "$@" <<'EOF'
import sys, json
for image in json.loads(sys.argv[1])["Images"]:
print image["ImageId"]
EOF
}
请注意$(</dev/stdin)
是$(cat)
的一种更有效的bash替代方式;由于shell内置支持,它甚至可以在/dev/stdin
作为文件不存在的操作系统上运行。
所有这些都经过如下测试:
extractImageIds <<<'{"Images": [{"ImageId": "one"}, {"ImageId": "two"}]}'
要从变量中有效地提供stdin,可以改为运行extractImageIds <<<"$variable"
。请注意,包装器中的"$@"
元素用于确保sys.argv
填充shell函数的参数 - 其中sys.argv
未被正在运行的Python代码引用,语法是可选的。