简体   繁体   English

在 bash 脚本中运行带有参数的 python 命令时的变量符号

[英]Variable notation when running python commands with arguments in a bash script

I have a bash script which is running a bunch of python script all with arguments.我有一个 bash 脚本,它正在运行一堆带有参数的 python 脚本。 In order to have a clean code, I wanted to use variables along the scripts为了有一个干净的代码,我想在脚本中使用变量

#!/bin/bash
START=0
SCRIPT_PATH="/opt/scripts/"
IP="192.168.1.111"

if [ "$START" = "0" ]; then
    printf "%s: Starting\n" "$DATE_TIME"

    PORT=1234
    TEST_FILE="$SCRIPT_PATH/Test Scripts/test.TXT"
    SCRIPT="$SCRIPT_PATH/script1.py"
    ARGS="-P $SCRIPT_PATH/script2.py -n 15 -p $PORT -i $IP"

    python "$SCRIPT" ${ARGS} -f "${TEST_FILE}" > ./out.log 2>&1 &

fi

This code is actually working but few things I don't understand :这段代码实际上有效,但我不明白的事情很少:

  1. Why, if I add quotes around ${ARGS} , the arguments are not parsed correctly by python ?为什么,如果我在${ARGS}周围添加引号,python 无法正确解析参数? What would be the best way to write this ?写这个的最好方法是什么?
  2. What is the best method to add -f "${TEST_FILE}" to the ARGS variable without python blocking on the whitespace and throwing the error: "$SCRIPT_PATH/Test " not found-f "${TEST_FILE}"ARGS变量的最佳方法是什么,而不会在空格上阻塞 python 并抛出错误: "$SCRIPT_PATH/Test " not found

When you wrap quotes around an argument list, the argument vector receives a single argument with everything that is wrapped in quotes and so, the argument parser fails to do its job properly and you have your issue.当您在参数列表周围用引号括起来时,参数向量会收到一个参数,其中的所有内容都用引号括起来,因此,参数解析器无法正常工作,并且您遇到了问题。

Regarding your second question, it is not easy to embed the quotes into the array, because the quotes will be parsed before being stored in the array, and then when you perform the array expansion to run the command, they will be missing and fail.关于你的第二个问题,把引号嵌入到数组中并不容易,因为引号在存入数组之前会被解析,然后当你执行数组扩展来运行命令时,它们会丢失并失败。 I have tried this several times with no success.我已经尝试了几次,但没有成功。

An alternative approach would mean that you modify a little your script to use a custom internal field separator (IFS) to manually tell what should be considered an argument and what not:另一种方法意味着您稍微修改脚本以使用自定义内部字段分隔符 (IFS) 来手动判断哪些应该被视为参数,哪些不是:

#!/bin/bash
START=0
SCRIPT_PATH="/opt/scripts/"
IP="192.168.1.111"

if [ "$START" = "0" ]; then
    printf "%s: Starting\n" "$DATE_TIME"

    PORT=1234
    TEST_FILE="$SCRIPT_PATH/Test Scripts/test.TXT"
    SCRIPT="$SCRIPT_PATH/script1.py"
    OLD_IFS=$IFS
    IFS=';'
    ARGS="$SCRIPT;-P;$SCRIPT_PATH/script2.py;-n;15;-p;$PORT;-i;$IP;-f;$TEST_FILE"
    python ${ARGS} > ./out.log 2>&1 &
    IFS=$OLD_IFS
fi

As you can see, I replace the spaces in ARGS with semicolons.如您所见,我用分号替换了 ARGS 中的空格。 This way, TEST_FILE variable contents will be considered as a single argument for bash and will be properly populated in argument vector.这样, TEST_FILE变量内容将被视为 bash 的单个参数,并将正确填充到参数向量中。 I'm also moving the script to the argument vector for simplicity, otherwise, Python will not get the proper script path and fail, due to this modification we did to IFS.为简单起见,我还将脚本移至参数向量,否则,由于我们对 IFS 进行了此修改,Python 将无法获得正确的脚本路径并失败。

I was thinking something like this (with some cruft edited out to make it a standalone example):我在想这样的事情(编辑了一些多余的东西以使其成为一个独立的例子):

#!/bin/bash
SCRIPT_PATH="/opt/scripts/"
IP="192.168.1.111"

PORT=1234
TEST_FILE="$SCRIPT_PATH/Test Scripts/test.TXT"
SCRIPT="$SCRIPT_PATH/script1.py"
set -a ARGS
ARGS=(-P "$SCRIPT_PATH/script2.py" -n 15 -p "$PORT" -i "$IP")
ARGS+=(-f "${TEST_FILE}")

python3 -c "import sys; print(*enumerate(sys.argv), sep='\n')" "${ARGS[@]}"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM