Linux bash: Присвоєння декількох змінних


121

Чи існує в linux bash щось подібне до наступного коду в PHP:

list($var1, $var2, $var3) = function_that_returns_a_three_element_array() ;

тобто ви призначаєте в одному реченні відповідне значення 3 різним змінним.

Скажімо, у мене є функція bash, myBashFuntionяка пише для stdout рядка "qwert asdfg zxcvb". Чи можна зробити щось на кшталт:

(var1 var2 var3) = ( `myBashFuntion param1 param2` )

Частина зліва від знака рівності звичайно не відповідає синтаксису. Я просто намагаюся пояснити, про що я прошу.

Однак, що працює:

array = ( `myBashFuntion param1 param2` )
echo ${array[0]} ${array[1]} ${array[2]}

Але індексований масив не такий описовий, як прості імена змінних.
Однак я міг би просто зробити:

var1 = ${array[0]} ; var2 = ${array[1]} ; var3 = ${array[2]}

Але це ще 3 твердження, яких я вважаю за краще уникати.

Я просто шукаю синтаксис ярликів. Це можливо?

Відповіді:


222

Перше, що мені спадає на думку:

read -r a b c <<<$(echo 1 2 3) ; echo "$a|$b|$c"

вихід є, не дивно

1|2|3

4
Чи все-таки потрібно змусити це працювати, якщо перша змінна містить пробіл?
Rucent88

7
@Michael Використання read -d "\n" v1 v2 <<<$(cmd)працює чудово. Дякую!
Rucent88

1
@LeeNetherton, хороший момент, хоча я не впевнений, чи потрібен статус повернення команди echo :-) Я думаю, що на момент написання відповіді bash, що підтримує цей синтаксис, був менш поширеним (як це встановлено за замовчуванням), хоча я я не на 100% впевнений.
Майкл Крелін - хакер

4
@ MichaelKrelin-хакер впевнений, що стан повернення echoбезглуздо, але я використовував цю методику для повернення декількох значень із сценарію, що мені було важливо про стан повернення. Я думав, що поділюся своїми висновками.
Лі Нешертон

1
Для забезпечення безпеки слід використовувати: read -r:do not allow backslashes to escape any characters
Том Хейл

18

Я хотів призначити значення масиву. Отже, розширюючи підхід Майкла Креліна , я зробив:

read a[{1..3}] <<< $(echo 2 4 6); echo "${a[1]}|${a[2]}|${a[3]}"

який дає:

2|4|6 

як і очікувалося.


2
Для розміщення значень у масиві вже є просте рішення, про яке я згадував у запитанні:a=( $(echo 2 4 6) ) ; echo ${a[0]} ${a[1]} ${a[2]}
GetFree

Так, я це не помітив. Я б заперечував, що моя пропозиція краще підходить для призначення більших масивів.
саундрейк

@soundray У вашому рішенні використовується розширення та герестрінг, тому що це, мабуть, я сумніваюся, що він буде добре працювати в тому сценарії (але я не перевіряв).
Каміло Мартін

Для забезпечення безпеки слід використовувати: read -r:do not allow backslashes to escape any characters
Том Хейл

5

Я думаю, це може допомогти ...

Для розбиття введених користувачем дат (мм / дд / рр. Р.) У моїх сценаріях я зберігаю день, місяць та рік у масив, а потім розміщую значення на окремі змінні таким чином:

DATE_ARRAY=(`echo $2 | sed -e 's/\// /g'`)
MONTH=(`echo ${DATE_ARRAY[0]}`)
DAY=(`echo ${DATE_ARRAY[1]}`)
YEAR=(`echo ${DATE_ARRAY[2]}`)

Чому б не уникнути 4 допоміжних оболонок плюс додатковий процес sed, а просто зробити все це в одному рядку:IFS=/ read -r m d y < <(echo 12/29/2009)
Amit Naidu

5

Іноді доводиться робити щось фанкі. Скажімо, ви хочете прочитати з команди (наприклад, приклад SDGuero дати), але ви хочете уникати декількох форк.

read month day year << DATE_COMMAND
 $(date "+%m %d %Y")
DATE_COMMAND
echo $month $day $year

Ви також можете ввести команду read, але тоді вам доведеться використовувати змінні в межах підзаголовка:

day=n/a; month=n/a; year=n/a
date "+%d %m %Y" | { read day month year ; echo $day $month $year; }
echo $day $month $year

призводить до...

13 08 2013
n/a n/a n/a

readКоманда не відбувається в субоболочке через дужки, це тому , що у вас є для читання команди на правій стороні труби. Вам потрібно запустити readкоманду в поточній оболонці, яку ви можете зробити такread day month year <<< `date "+%d %m %Y"`
пневматика

Ні - read трапляється, але сфера змінних, на які вона читає, випадає із сфери застосування, коли закінчується нижня оболонка трубопроводу.
Отей

1
Мій коментар стосувався причини, чому прочитане трапляється в нижній частині, і я розумію, що зараз я неправильно прочитав те, що ви написали. Я подумав, що ти маєш на увазі, що нижня оболонка створена тому, що ти використовував фігурні дужки навколо складеного оператора. Але! Причиною, яку ви наводили в цьому прикладі, було уникнення розгортання, але не буде також і роздвоєна вилка?
пневматика

Перший приклад вимагає рівно одного вила: щоб bash міг запустити команду date. У другому прикладі ви налаштовуєте трубопровід між датою та підрозділом. Я думаю, що Баш в ці дні є досить розумним, щоб насправді не розщедритися в підпакет, але я не впевнений у цьому. У будь-якому випадку, схоже, що це було б :)
Отей,

0

Глава 5 Кухонної книги Bash від O'Reilly обговорює (з деякою довжиною) причини вимоги у змінному призначенні, що навколо знаку '=' не має пробілів.

MYVAR="something"

Пояснення має щось спільне з розмежуванням імені команди та змінної (де '=' може бути коректним аргументом).

Це все схоже на виправдання після події, але в будь-якому випадку не згадується спосіб віднесення до списку змінних.


Так, я знаю. Я просто додав додаткові місця тут і там заради читабельності
GetFree

Дійсно, це погана мотивація: що робити, якщо ' ;' є вагомим аргументом? Коли я пишу ls ; cdце все ще дзвонить lsі cdнезважаючи на пробіли. Якщо я хочу , щоб список каталогів , званих ;і cdя можу тільки надрукувати ls ';' cd.
PieterNuyts
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.