У меня есть bootstrap (bash), который должен отфильтровать некоторые аргументы, прежде чем он запустит скрипт pperon propper.
Проблема в том, что всякий раз, когда я передаю строку с пробелами в бутстрап, она получает искалечение, когда она прибывает на 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
Цитирование почти всегда фиксирует этот тип проблемы.
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 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}
((i++)); marg=${@:i:1}
(конечно, если вы предпочитаете отдельные строки).
Я изменил ваш массив на более простую форму +=
и добавил к ним цитату.
getopt
,argparse
илиoptparse
(не рекомендуется!). сделайте себе одолжение и используйте их, это намного проще, чем синтаксический анализ bash с использованиемprintf
и ручного цитирования строк ...