2016-03-09 3 views
-1

Я пытаюсь сделать функцию меню, и следующий сегмент сценария, который предназначен для разделения запятых списка значений в массив:Почему мой список лишен запятых?

IFS=, 
read -r -a optionList <<< $3 

Однако, результат всегда один вход без запятых

echo ${#optionList[@]} 
echo ${optionList[0]} 

дает выходной сигнал, который выглядит следующим образом:

1 
Option 1 Option 2 Option 3 

Однако следующее, как и ожидалось:

echo $3 

дает выход:

Option 1,Option 2,Option 3 

Что я здесь отсутствует?

+0

Обратите внимание, что канонический путь будет следующим: 'IFS =, read -r -d '' -a optionList <<(printf '% s, \ 0'" $ 3 ")'. –

ответ

2

Есть две основные проблемы здесь : установка IFS влияет на многие вещи в том, как оболочка анализирует строки, в том числе некоторые, которых вы не ожидаете; и оставляя $3 unquoted, это может стать одной из вещей, которые перепутались.

Что происходит, когда вы ссылаетесь на $3 без двойных кавычек вокруг него, оболочка разбивает его на «слова», используя $IFS в качестве разделителя (ов). В вашем примере это дает три слова: «Вариант 1», «Вариант 2» и «Вариант 3». В контексте <<< он затем объединяет их обратно, используя пространство как разделитель (что странно, но это то, что он делает), давая «Вариант 1 Вариант 2 Вариант 3». Вы можете увидеть этот эффект отдельно:

$ foo="Option 1,Option 2,Option 3" 
$ IFS=, 
$ cat <<< $foo 
Option 1 Option 2 Option 3 

Итак команда read получает «Вариант 1 Вариант 2 Варианта 3» в качестве входных данных, разбивает его на основе $IFS («»), приходит к выводу, что нет никаких разделителей слов, поэтому он помещает все это в элемент # 0 optionList.

Вы можете исправить это путем двойного цитирования $3, чтобы предотвратить расщепление слов, но у вас появятся другие проблемы, потому что IFS также повлияет на множество других вещей на вашем скрипте. Поэтому вы должны также следовать рекомендации anubhava, чтобы сделать IFS назначением префикса в команде read, так что влияет только на эту команду, а не на глобальное изменение того, как оболочка анализирует строки.

Так как с изменениями, моя рекомендация состоит в том, чтобы использовать:

IFS=, read -ra optionList <<< "$3" 

... так же, как рекомендации анубхава в.

+0

Я поддержал другие ответы, поскольку они были полезны, но я принимаю ваши как самые полные. Тем более, что вы упомянули термин «префикс», доступный для поиска, который помог мне узнать больше о префиксах команд в целом. – BryKKan

2

Вы можете использовать IFS инлайн как:

str='Option 1,Option 2,Option 3' 
IFS=, read -ra optionList <<< "$str" 

Это позволит избежать разлагающего IFS для текущей оболочки.

Проверьте выход:

declare -p optionList 
declare -a optionList='([0]="Option 1" [1]="Option 2" [2]="Option 3")' 
+0

Спасибо! Я не понимал, что вы можете присвоить значение в той же строке! – BryKKan

+2

Да 'IFS' не следует устанавливать глобально в оболочке, чтобы не влиять на поведение другой команды. – anubhava

+0

Я сделал небольшое исследование и в итоге использовал &&, так как я предпочел бы получить массив без использования неправильного разделителя – BryKKan

3

Адрес переменной $3.

При установке IFS сессии премудрого, и не процитировать любую переменную, эта переменная будет страдать от слова расщепления в соответствии со значением (ами) IFS (, в данном случае). Это делается с помощью оболочки, прежде чем read получает значения переменных, следовательно read получает Option 1 Option 2 Option 3 вместо желаемого Option 1,Option 2,Option 3 работать на:

$ IFS=,; echo $bar 
Option 1 Option 2 Option 3 

$ IFS=,; echo "$bar" 
Option 1,Option 2,Option 3 

С вашей проблемой:

$ echo $bar 
Option 1 Option 2 Option 3 


#### Without quoting 

$ IFS=, read -ra foo <<< $bar 

$ echo "${#foo[@]}" 
1 

$ echo "${foo[0]}" 
Option 1 Option 2 Option 3 


#### With Quoting 

$ IFS=, read -ra foo <<< "$bar" 

$ echo "${#foo[@]}" 
3 

$ echo "${foo[0]}" 
Option 1 

$ echo "${foo[1]}" 
Option 2 

$ echo "${foo[2]}" 
Option 3 
+0

Спасибо! Это сработало! Если вы не возражаете, не могли бы вы рассказать мне, что именно происходит, когда оно не цитируется? Является ли это чем-то связанным со всеми различными расширениями, которые происходят повсюду, что я до сих пор не понимаю? – BryKKan

+0

@Bryan Проверьте мои изменения – heemayl

+0

'IFS = ;; read ... 'также вызовет утечку' IFS' в текущей среде оболочки и повлияет на другие команды оболочки – anubhava

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