2013-06-13 13 views
2

Я пишу скрипт bash, который перебирает результат подстановки команды, а затем пытается выполнить другую подстановку команд внутри тела цикла. Вот код:Как переменная IFS Bash влияет на подстановку команд?

#!/usr/bin/bash 

IFS=$'\n' 

for i in $(xmllint --xpath "string(/*[local-name()='Project'])" gsGDAL/gsGDAL.vcxproj.user) 
do 
    IFS=' ' #attempted with and without this line 
    "$(awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i))" 
    IFS=$'\n' #attempted with and without this line 
done 

Я установил стандарт IFS для новой строки так, чтобы петля перебирает каждую строку вывода команды xmllint, а не итерация каждого разделенных пробелов слова. Тем не менее, это приводит к сбою подстановки команды в цикле. Некоторые отладки привели к выводу о том, что суть проблемы заключается в следующем:

#!/usr/bin/bash 

IFS=$'\n' 

$(echo export TEST="test") 

, который дает ошибку:

./x.sh: line 6: export TEST=test: command not found 

Вы можете видеть, что я попытался исправить в первом примере кода путем сброса IFS в пределах цикла. Это не сработало.

Я понимаю, что я могу решить проблему, используя другую идиому для скрипта.
, например. процесс заменяет команду xmllint на awk вместо того, чтобы делать awk на каждой отдельной строке, чтобы назвать одну возможность. Комментариев к этому вопросу приветствуется, однако, пожалуйста, представить ответы на соответствующий следующему:

  1. Почему установку ИФСА для новой строки испортят подстановки команд сгенерированных экспорта?
  2. Почему сброс IFS в цикле не устраняет проблему?

UPDATE: За обсуждение с Barmar, IFS используется для софистики после команды/расширений переменных.

ответ

4

Я не думаю, что IFS является причиной ваших проблем. Есть две проблемы с вашим кодом:

  1. Вы попали $(awk ...) в двойных кавычках, так ни слова Расщепление не делается. Поэтому он обрабатывает export varname="value" как имя команды - это пространство является частью имени команды, а не разделителем между командой и аргументом.

  2. Даже без двойных кавычек это не сработает, потому что обработка цитаты не выполняется в результате подстановки команды, только разделение слов и расширение подстановки. Таким образом, двойные кавычки в вашей команде export будут включены как буквенные символы в присваиваемые значения.

Решение этой проблемы, как отметил mplf, заключается в использовании eval:

eval "$(awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i))" 
+0

Спасибо. Интересно, можете ли вы сказать мне, почему установка IFS для новой строки препятствует правильному выполнению результата подстановки команды. Это потому, что оболочка использует IFS для tokenize команды, заставляя 'export TEST =" test "' интерпретироваться как единый токен во время разбора?И если да, то почему eval не подлежит этому (мой код работает без перезагрузки IFS в пространстве, когда я использую eval)? – user2141130

+0

Да, это так. При анализе командной строки оболочка использует разбиение слов, чтобы найти команду - это просто первое слово. Если вы измените параметр разделения слов, это повлияет на это. – Barmar

+0

Отлично, спасибо. Не использует ли IFAL IFS? – user2141130

2

Используйте eval, чтобы оценить строку, возвращаемую из подоболочки.

IFS=' ' #attempted with and without this line 
eval $(awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i)) 
IFS=$'\n' #attempted with and without this line 

 Смежные вопросы

  • Нет связанных вопросов^_^