чтение аргументов для программы из пользовательского файла и запуск этой программы с этими аргументами

все!

Мне нужно прочитать аргументы из файла «данные», который состоит из таких строк, как:

-a -camb="1 0.5 1",diff="1 0 0" -q=5
-a -camb="0 1 0" -p -q -f=10
...

Затем эти аргументы должны быть переданы программе ./test внутри скрипта:

#!/bin/bash

while read line
do
    ./test "$line"
done < "./data"

проблема в том, что "$line" передается как argv[1] в ./test, а не как последовательность argv[1], argv[2], argv[3]

Как я могу разделить строковую строку на несколько аргументов? т.е. ./test должен принимать argv[1], argv[2] и так далее?

Обратите внимание, что -camb="1 0.5 1",diff="1 0 0" должен быть целым аргументом, argv[2]!


person Anton Vasilev    schedule 08.07.2011    source источник


Ответы (2)


Вы можете использовать eval для этого:

#!/bin/bash

while read line
do
    eval "./test $line"
done < "./data"

Однако здесь есть большое предупреждение: eval может сделать больше интерпретации содержимого файла, чем вы хотите. Например, если он содержит какие-либо перенаправления ввода-вывода (например, >somefile), они будут применены. Точно так же $variable будет подставляться, ; somecommand будет выполняться как отдельная команда и т. д. В основном, если содержимое файла данных недостаточно чистое, вы можете получить некоторые неожиданные и потенциально опасные результаты.

person Gordon Davisson    schedule 08.07.2011

Кавычки буквальные, а не синтаксические, что означает, что они не будут обрабатываться так же, как на оболочка. Но вы можете справиться с ними, установив их в массив:

$ params(){
    for param in "$@"
    do
        echo "$param"
    done
}
$ while IFS= read -r line
do
    declare -a par="($line)"
    params "${par[@]}"
    echo
done < data
-a
-camb=1 0.5 1,diff=1 0 0
-q=5

-a
-camb=0 1 0
-p
-q
-f=10

PS: Не используйте eval.

person l0b0    schedule 08.07.2011
comment
@IObO: Почему это работает? Что такое IFS=? Зачем использовать read -r? Спасибо - person grok12; 08.07.2011
comment
Подробности о том, как это работает, можно найти в превосходных статьях о ключевых словах (IFS, while read, параметры) и страницу Bash man. Если вы действительно хотите изучить Bash, эти страницы и все ссылки оттуда на вес золота. - person l0b0; 09.07.2011
comment
Спасибо за ссылки. Теперь я понимаю ваш сценарий, за исключением одного: почему ваш оператор declare разбивает строковую переменную на символах тире? Я озадачен этим. - person grok12; 10.07.2011
comment
Это не так :) Во-первых, "($line)" расширяется, например, до. (-a -camb=0\ 1\ 0 -p -q -f=10), а затем IFS (пробел+табуляция+новая строка по умолчанию) используется для разделения на массив. Экранированные символы, такие как \ , не разбиваются. - person l0b0; 11.07.2011
comment
Но IFS устанавливается равным null в инструкции while. Разве это не все еще null для объявления объявления? - person grok12; 12.07.2011
comment
Это так, но, насколько я понимаю, для такого рода операторов Bash использует значение по умолчанию $' \t\n'. - person l0b0; 12.07.2011
comment
ОК, а затем пробелы внутри двойных кавычек в разделе 6.7 ссылки на bash, в котором говорится: Эти индексы отличаются только тогда, когда слово появляется в двойных кавычках. Если слово заключено в двойные кавычки, ${name[*]} заменяется на одно слово со значением каждого члена массива, разделенным первым символом переменной IFS. Теперь я собираюсь найти документацию по значению IFS в объявлении. - person grok12; 12.07.2011
comment
Я определил (используя echo IFS | cat -vte), что установка IFS на null в операторе while не сохраняется внутри do. Я не могу понять, почему, поэтому я собираюсь опубликовать новый вопрос. - person grok12; 12.07.2011
comment
При подготовке моего нового вопроса я нашел что-то, что привело меня к bash ref 3.7.4, в котором говорится, что среда для любой простой команды или функции может быть временно расширена путем добавления к ней префикса с назначениями параметров, как описано в Параметры оболочки. Эти операторы присваивания влияют только на среду, видимую этой командой. Это объясняет, почему IFS отличается для команды чтения и объявления объявления. - person grok12; 12.07.2011