привязка строки к массиву вместо использования чтения в скрипте bash?

#arrays #bash #parsing

#массивы #bash #синтаксический анализ

Вопрос:

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

Я вижу, что предлагаемый подход обычно

 IFS=: read -r -a myarray <<< "$mystring"
 

Вместо этого я использовал команду, которая мне кажется более простой:

 IFS=: myarray=($mystring)
 

Более того, на моем КОМПЬЮТЕРЕ это работает. Смотрите сценарий ниже

 #!/bin/bash

mystring="var01:var02:var03:var04"

IFS=: myarray=($mystring)

echo "first variable is" "${myarray[0]}"
echo "second variable is" "${myarray[1]}"
echo "..."
 

вывод

 first variable is var01
second variable is var02
...
 

Однако, поскольку я не нашел такого примера в Интернете, я не уверен, что это правильно…

В чем проблема использования этого в скрипте bash? Соответствует ли это стандарту?

Спасибо за ваш совет.

Ответ №1:

Хороший первый вопрос. У предложенной вами альтернативы есть проблемы. Сначала рассмотрим

 $ str='a:%:*'
$ IFS=: read -r -a arr <<< "$str"
$ echo "${arr[@]}"
a % *
 

Результат является ожидаемым. Поскольку "$str" он заключен в кавычки в herestring, он не подвергается расширению имени файла (так называемому глобированию), и все в порядке.

С другой стороны…

 $ str='a:%:*'
$ IFS=: arr=($str)
$ echo "${arr[@]}"
a % 07-13:37:38.png 07-13:37:49.png Documents Downloads Pictures Music Xresources
 

Во втором случае $str не заключен в кавычки и подвергается расширению имени файла, что означает * , что он расширяется до всех файлов в моем текущем каталоге! Увы!

Ни одна из этих форм не совместима с POSIX, поскольку POSIX не определяет массивы в оболочках. Но оба они полностью допустимы в Bash, хотя, как показано, они делают разные вещи.

Ссылка в руководстве Bash: расширение имени файла.


Как вы уже заметили, вы можете использовать set -f для отключения расширения имени файла. Это решило бы проблему IFS=: arr=($str) , но некоторых может удивить. Если вы идете этим путем, установите его обратно с set f помощью параметра сразу после этой строки, иначе настройка будет применена ко всей остальной части скрипта. Это увеличивает сложность решения, поэтому я рекомендую избегать этого, когда это возможно.

Комментарии:

1. Я прочитал в мануале Bash «После разделения слов, если только не была установлена опция -f». Итак, я полагаю, чтобы избежать этого, я должен сначала установить de option -f, но это увеличивает сложность решения. Я еще разберусь в этом, но я понимаю проблему