【问题标题】:Bash parse & concatenate arguments for executing python用于执行 python 的 Bash 解析和连接参数
【发布时间】:2012-05-21 17:30:18
【问题描述】:

我有一个引导程序 (bash),它应该在启动 propper python 脚本之前过滤掉一些参数。

问题是,每当我将带有空格的字符串传递到引导程序时,一旦到达 python,它就会被破坏

例如执行

./myBootStrap.sh --preload "argl bargl" -j -as -argl --postload "my Test"

打印这个

Executing myBootStrap --preload "argl bargl" -j -as -argl --postload "my Test"

我的 python 脚本打印它的参数

got arguments ['myBootStrap','--preload', '"argl', 'bargl"', '-j', '-as', '-argl', '--postload', '"my', 'Test"']

如您所见,“argl bargl”和“my Test”被拆分为 ['"argl','bargl"'] & ['"my', 'Test"'],而不是保持组合。

知道我的代码有什么问题吗?

谢谢大家!


myBootStrap.sh

#!/bin/bash
declare -a argv
for ((i=1;i<=${#@};i+=1))
do

   arg=${@:i:1}

   if [[ "$arg" == "--preload"* ]];then
      i=$i+1
      marg=${@:$((i)):1}
      preLoadO=$arg
      preLoadA=" \"${marg}\""
      argv=("${argv[@]}" $arg)
      argv=("${argv[@]}" $preLoadA)

   elif [[ "$arg" == "--postload"* ]];then
      i=$i+1
      marg=${@:$((i)):1}
      postLoadO=$arg
      postLoadA=" \"${marg}\""
      argv=("${argv[@]}" $arg)
      argv=("${argv[@]}" $postLoadA)       
   else          
      argv=("${argv[@]}" $arg)
   fi
done

arguments=$(printf " %s" "${argv[@]}")
arguments=${arguments:1}

echo "Executing myBootStrap" $arguments 
exec myBootStrap $arguments 

和python脚本myBootStrap

#!/usr/bin/env python
import sys
print 'got arguments %s'%sys.argv

【问题讨论】:

  • python 具有允许您解析命令行参数的内置功能:getoptargparseoptparse(已弃用!)。帮自己一个忙并使用它们,然后使用 printf 在 bash 中解析参数并手动引用字符串要容易得多...
  • 不幸的是,我必须先通过 bash,因为它设置了很多环境变量等,所以没有办法绕过 bash :(
  • 那我推荐GNU getopt
  • @Seb:你也可以在 Python 中设置环境变量,使用os.environ
  • @mata: I wouldn't.

标签: python bash unix arguments


【解决方案1】:

引用几乎总能解决这类问题。

exec myBootStrap "$arguments"

演示:

$ a='"abc def" ghi'
$ echo "$a"
"abc def" ghi
$ args $a
3 args: <"abc> <def"> <ghi>
$ args "$a"
1 args: <"abc def" ghi>
$ cat args
#! /bin/sh
# Greg Wooledge's args script
printf "%d args:" $#
printf " <%s>" "$@"
echo

编辑

好的,我花了一些时间分析您的 Bash 脚本实际上在做什么。只是尝试产生与给出的完全相同的参数,然后将它们传递给 Python 脚本。

它可以简单地替换为:

exec myBootStrap "$@"

但是,我认为您实际上正在那里进行一些我们看不到的其他处理。在此基础上,我修改了您的脚本,以便将其用作类似内容的基础。

#!/bin/bash
declare -a argv
for ((i = 1; i <= $#; i += 1))
do

   arg=${@:i:1}

   if [[ "$arg" == "--preload"* ]]; then
      marg=${@: ++i:1}
      preLoadO=$arg
      preLoadA="${marg}"
      argv+=("$arg")
      argv+=("$preLoadA")

   elif [[ "$arg" == "--postload"* ]]; then
      marg=${@: ++i:1}
      postLoadO=$arg
      postLoadA="${marg}"
      argv+=("$arg")
      argv+=("$postLoadA")
   else
      argv+=("$arg")
   fi
done

exec ./myBootStrap "${argv[@]}"

参数必须作为带引号的数组传递。您已经构建了阵列,但随后您使用printf 将其展平。

请注意,数组切片已经是算术上下文,因此您不需要在其中使用$(())。我删除了单独的i=i+1(它连接了字符,所以你会在一段时间后得到1+1+1+1),然后在数组切片中放置一个预增量。第一个加号之前的空格是必需的,因为:+ 在大括号扩展中很重要。如果您愿意,您可以像这样单独进行增量:((i++)); marg=${@:i:1}(当然,如果您愿意,可以在单独的行中)。

我将您的数组追加更改为更简单的 += 表单,并为它们添加了引用。

【讨论】:

  • 不幸的是,如果您运行 python 脚本,只需将最后一行从 $arguments 更改为 "$arguments",python 脚本仍然会拆分参数
猜你喜欢
  • 2011-02-20
  • 2021-11-02
  • 2018-08-27
  • 2013-05-11
  • 2013-01-01
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多