Разбор Bash & объединение аргументов для выполнения Python

1

У меня есть 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
  • 1
    Python имеет встроенные возможности, позволяющие вам анализировать аргументы командной строки: getopt , argparse или optparse (не рекомендуется!). сделайте себе одолжение и используйте их, это намного проще, чем синтаксический анализ bash с использованием printf и ручного цитирования строк ...
  • 0
    к сожалению, мне сначала нужно пройти через bash, потому что он устанавливает множество переменных env и т. д., так что нет никакого способа обойти bash :(
Показать ещё 5 комментариев
Теги:
arguments

1 ответ

4
Лучший ответ

Цитирование почти всегда фиксирует этот тип проблемы.

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} (конечно, если вы предпочитаете отдельные строки).

Я изменил ваш массив на более простую форму += и добавил к ним цитату.

  • 0
    к сожалению, нет, если вы запустите скрипт python, просто изменив последнюю строку с $ arguments на "$ arguments", скрипт python по-прежнему разделит аргументы
  • 0
    @Seb: Пожалуйста, смотрите мой отредактированный ответ.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню