Разделение слов в bash с вводом из файла - PullRequest
1 голос
/ 03 февраля 2011

У меня возникли проблемы с получением bash для хорошей игры с парсингом слов из командной строки.Я считаю, что проще всего привести пример, поэтому без дальнейших церемоний, здесь мы идем.

Это скрипт test.sh:

<code>#!/bin/bash
echo "inside test with $# arguments"</p>

<p>if [[ $# -eq 0 ]]
then
    data=<code>cat data.txt</code>
    echo ./test $data
    ./test $data
else
    for arg in "$@"
    do
        echo "Arg is \"$arg\""
    done
fi

А вот данные файла.txt:

<code>"abc 123" 1 2 3 "how are you"

Требуемый вывод

<code>$ test.sh

равен

<code>
inside test with 0 arguments
./test "abc 123" 1 2 3 "how are you"
inside test with 5 arguments
Arg is "abc 123"
Arg is "1"
Arg is "2"
Arg is "3"
Arg is "how are you"

Но вместо этого яполучение

<code>
inside test with 0 arguments
./test "abc 123" 1 2 3 "how are you"
inside test with 8 arguments
Arg is ""abc"
Arg is "123""
Arg is "1"
Arg is "2"
Arg is "3"
Arg is ""how"
Arg is "are"
Arg is "you""

Действительно раздражает то, что если я выполняю команду, которая выводится из строки 7 test.sh, я делаю получаю желаемый результат (безпервые две строки, конечно).

Так, по сути, есть ли способ получить bash для разбора слов, если дан вход, который был прочитан из файла?

Ответы [ 3 ]

1 голос
/ 03 февраля 2011

Нет необходимости вызывать скрипт дважды.

Если вы обнаружите, что аргументов нет, вы можете использовать set, чтобы изменить их на что-то другое, например:

#!/bin/bash

if [ $# -eq 0 ]
then
    echo "inside test with $# arguments"
    eval set -- $(<data.txt)
fi

echo "inside test with $# arguments"
for arg in "$@"
do
    echo "Arg is \"$arg\""
done
1 голос
/ 03 февраля 2011

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

eval ./test "$data"

Вы должны быть осторожны , чтобы знать, что вы можете доверять содержимому файла при использовании eval. Чтобы продемонстрировать почему, добавьте ; pwd в конце строки в вашем файле данных. Когда вы запустите скрипт, будет напечатан текущий каталог. Представь, если бы это было что-то разрушительное.

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

while IFS=$'\t' read -r -a array
do
    for item in "${array[@]}"
    do
        something with "$item"
    done
done < data.txt

Вам не нужно заключать в кавычки поля, содержащие пробелы.

Это исправление того, что, как я полагаю, было опечаткой в ​​вашем вопросе:

data=$(cat data.txt)
0 голосов
/ 03 февраля 2011

Да, просто замените

./test $data

с

eval ./test $data
...