为可读性而清理python时,Long curl命令无法导入python

为可读性而清理python时,Long curl命令无法导入python,python,json,bash,curl,Python,Json,Bash,Curl,我有一个长curl命令,在另一个答案中用反斜杠进行了清理,以增加其可读性。唯一的问题是,它抛开了我在其中使用的一小段python代码。工作一衬板如下所示: 它与API对话,我已经删除了关键变量以及与我的公司相关的任何内容 NETWORK_ID=$(curl -L -H 'X-Cisco-Meraki-API-Key: mykeygoeshere' -X POST -H'Content-Type: application/json' --data-binary '{"name":"'"$NETWO

我有一个长curl命令,在另一个答案中用反斜杠进行了清理,以增加其可读性。唯一的问题是,它抛开了我在其中使用的一小段python代码。工作一衬板如下所示: 它与API对话,我已经删除了关键变量以及与我的公司相关的任何内容

NETWORK_ID=$(curl -L -H 'X-Cisco-Meraki-API-Key: mykeygoeshere' -X POST -H'Content-Type: application/json' --data-binary '{"name":"'"$NETWORK_NAME"'", "type":"appliance", "timeZone":"'"$TIME_ZONE"'"}' 'https://dashboard.meraki.com/api/v0/organizations/foobar/networks' | python -c "import sys, json; print json.load(sys.stdin)['id']")
当使用转义字符进行清理时,它看起来更好,增加了可读性和编辑能力。我希望它的外观如下:

NETWORK_ID=$(curl -L -H 'X-Cisco-Meraki-API-Key: mykeygoeshere'\
    -X POST -H'Content-Type: application/json' --data-binary '{"name":"'"$NETWORK_NAME"'",\
    "type":"appliance", "timeZone":"'"$TIME_ZONE"'"}'\
    'https://dashboard.meraki.com/api/v0/organizations/foobar/networks'\
    | python -c "import sys, json; print json.load(sys.stdin)['id']")
但当我执行上述代码时,我会抛出以下错误:

% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   285    0   202  100    83    516    212 --:--:-- --:--:-- --:--:--   516
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 291, in load
    **kw)
  File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded

一行程序和可读代码之间的功能区别是什么?重申一下,一行程序顺利完成,没有问题。带有转义字符的代码不存在。如何让Python导入在这些条件下正常工作?

< p>你在-DATA二进制引用的参数值中间分裂,所以下一行的空格被包含在值中。

您希望将整个参数保持在一行,如:

... --data-binary \
   '{"name":"'"$NETWORK_NAME"'", "type":"appliance", "timeZone":"'"$TIME_ZONE"'"}' \
   ...
或者将该字符串放入变量中,并使用该字符串:

json='{"name":"'"$NETWORK_NAME"'", "type":"appliance", "timeZone":"'"$TIME_ZONE"'"}'
networkId=$(curl ... --data-binary "$json" \
            ...)

基本方法是有缺陷的。您不应该尝试使用shell参数插值生成JSON,因为shell参数中的值不一定是有效的JSON值。想想SQL注入。即使对于硬编码的JSON,从here文档中读取也比正确引用要简单。在这两种情况下,最好使用适当的工具(如jq或另一个Python脚本)来生成JSON,而不是手工构建

最后,定义一个从命令替换内部调用的函数,以更可读的方式格式化所有内容

get_network_id () {
    local -a curl_options jq_options
    curl_options=(
      -L
      -H 'X-Cisco-Meraki-API-Key: mykeygoeshere'
      -X POST
      -H 'Content-Type: application/json'
      --data-binary @-
      )
    url='https://dashboard.meraki.com/api/v0/organizations/foobar/networks'

    jq_options=( -n --arg netname "$NETWORK_NAME" --arg tz "$TIME_ZONE" )
    jq_filter='
    {
      name: $netname,
      type: "appliance",
      timeZone: $tz
    }'

    jq "${jq_options[@]}" "$jq_filter" |
      curl "${curl_options[@]}" "$url"  |
      jq -r '.id'
}

NETWORK_ID=$(get_network_id)

您还可以将网络名称和时区参数设置为函数的参数,而不是全局变量。

您没有提供curl命令的输出,假设您的curl调用正确并打印出有效的json,python2应该从stdin读取:

cat /usr/lib/python3.6/site-packages/zmq/utils/config.json | python2 -c 'import sys, json; print(json.loads(sys.stdin.read()))'
返回:

{u'have_sys_un_h': True, u'allow_legacy_libzmq': False, u'zmq_prefix': u'', u'no_libzmq_extension': False, u'build_ext': {}, u'bdist_egg': {}, u'skip_check_zmq': False, u'libzmq_extension': False, u'bundle_msvcp': None}