У меня есть скрипт bash, который строит командную строку в строке на основе некоторых параметров, прежде чем выполнять ее за один раз. Предполагается, что части, которые соединяются с командной строкой, должны быть разделены конвейерами, чтобы облегчить «поток» данных через каждый компонент.
Очень упрощенный пример:
#!/bin/bash
part1=gzip -c
part2=some_other_command
cmd="cat infile"
if [ ! "$part1" = "" ]
then
cmd+=" | $part1"
fi
if [ ! "$part2" = "" ]
then
cmd+=" | $part2"
fi
cmd+="> outfile"
#show command. It looks ok
echo $cmd
#run the command. fails with pipes
$cmd
По некоторым причинам трубы, кажется, не работают. Когда я запускаю этот скрипт, я получаю разные сообщения об ошибках, относящиеся обычно к первой части команды (перед первым каналом).
Итак, мой вопрос: возможно ли построить команду таким образом, и как лучше это сделать?
infile
существует в текущем каталоге?Ответы:
Все зависит от того, когда все оценивается. Когда вы печатаете
$cmd
, вся остальная часть строки передается в качестве аргументов первому слову в$cmd
.Это показывает, что аргументам, переданным
echo
команде, являются: "/etc/passwd
", "|
" (символ вертикальной черты), "wc
" и "-l
".От
man bash
:источник
Одним из решений этой проблемы, для дальнейшего использования, является использование «eval». Это гарантирует, что любой способ интерпретации строки bash будет забыт, и все это будет прочитано так, как если бы оно было набрано непосредственно в оболочке (что именно то, что нам нужно).
Таким образом, в приведенном выше примере, заменяя
с
решил это.
источник
eval foo "a b"
будет так же, какeval foo "a" "b"
.@waltinator уже объяснил, почему это не работает, как вы ожидали. Другой способ обойти это использовать
bash -c
для выполнения вашей команды:источник
bash -c
, а использовать егоeval
для выполнения команды в текущем процессе.Возможно, лучший способ сделать это состоит в том, чтобы избежать использования
eval
и просто использования массива Bash, и это встроенное расширение для построения всех аргументов и последующего их выполнения в команде.источник