为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 popen 命令行参数包含单引号和双引号?

如何使用 popen 命令行参数包含单引号和双引号?

慕丝7291255 2022-10-06 16:55:01
我想在 python3中运行以下jq命令。subprocess.Popen()$ jq  'INDEX(.images[]; .id) as $imgs | {    "filename_with_label":[         .annotations[]        | select(.attributes.type=="letter" )        | $imgs[.image_id] + {label:.text}        | {id:.id} + {filename:.file_name} + {label:.label}     ]   }' image_data_annotation.json > image_data_annotation_with_label.json请注意,第一个命令行参数包含点、美元符号、单引号内的双引号。仅供参考,jq是用于处理 json 文件的 JSON 处理器实用程序。我编写了以下 python3 脚本,用于使用jq实用程序自动处理 JSON 文件。#!python3# file name: letter_image_tool.pyimport os, subprocess"""command line example to automate$ jq  'INDEX(.images[]; .id) as $imgs | {    "filename_with_label":[         .annotations[]        | select(.attributes.type=="letter" )        | $imgs[.image_id] + {label:.text}        | {id:.id} + {filename:.file_name} + {label:.label}     ]   }' image_data_annotation.json > image_data_annotation_with_label.json"""# define first command line argumentjq_filter='\'INDEX(.images[]; .id) as $imgs | { "filename_with_label" : [ .annotations[] | select(.attributes.type=="letter" ) | $imgs[.image_id] + {label:.text} | {id:.id} + {filename:.file_name} + {label:.label} ] }\''input_json_files= [ "image_data_annotation.json"]output_json_files= []for input_json in input_json_files:    print("Processing %s" %(input_json))    filename, ext = os.path.splitext(input_json)    output_json = filename + "_with_label" + ext    output_json_files.append(output_json)    print("output file is : %s" %(output_json))    #jq_command ='jq' + " " +  jq_filter, input_json + ' > ' +  output_json    jq_command =['jq', jq_filter,  input_json + ' > ' +  output_json]    print(jq_command)    subprocess.Popen(jq_command, shell=True)第一个参数应该像上面的片段一样用单引号括起来,但我的脚本不处理它。我认为主要问题与第一个命令行参数(jq_filter在上面的 python 脚本中)中使用的点、美元符号、单引号和双引号有关。但是我不知道如何处理这种与bash相关的复杂元字符。我应该怎么做才能解决以上问题?
查看完整描述

1 回答

?
白板的微信

TA贡献1883条经验 获得超3个赞

您需要单引号的原因是为了防止 shell 对您的参数进行任何扩展。这是一个问题,只有在使用shell=True. 如果未设置,shell 将永远不会触及您的参数,也无需“保护”它们。


然而,shell 也负责stdout重定向(即[... '>', output_json])。不使用 shell,需要在 Python 代码中处理重定向。然而,这就像将参数添加stdout=...到Popen.


总而言之,这意味着您的代码可以重写为


import os

import subprocess


# Still define first command line argument with triple quotes for readability

# Note that there are no single quotes though

jq_filter = """INDEX(.images[]; .id) as $imgs | {

       "filename_with_label" : [

        .annotations[]

       | select(.attributes.type=="letter" )

       | $imgs[.image_id] + {label:.text}

       | {id:.id} + {filename:.file_name} + {label:.label} ] }"""


input_json_files = ["image_data_annotation.json"]

output_json_files = []


for input_json in input_json_files:

    print("Processing %s" % (input_json))

    filename, ext = os.path.splitext(input_json)

    output_json = filename + "_with_label" + ext

    output_json_files.append(output_json)

    print("output file is : %s" % (output_json))


    # Keep command as list, since this is what we need when NOT using shell=True

    # Note also that the redirect and the output file are not parts of the argument list

    jq_command = ['jq', jq_filter,  input_json]


    # shell keyword argument should NOT be set True

    # Instead redirect stdout to an out_file

    # (We must open the file for writing before redirecting)

    with open(output_json, "w") as out_file:

        subprocess.Popen(jq_command, stdout=out_file)

通常建议不要使用shell=True,因为这会打开另一个针对代码的攻击向量,因为注入攻击可以完全访问 shell。此外,不使用 shell 的另一个小好处是,它将减少创建的子进程的数量,因为不需要额外的 shell 进程。


查看完整回答
反对 回复 2022-10-06
  • 1 回答
  • 0 关注
  • 181 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信