Чи потрібні лапки для призначення місцевих змінних?


36

Чи можу я безпечно опустити цитати в правій частині місцевого завдання?

function foo {
    local myvar=${bar}
    stuff()
}

Мене в основному цікавить bash, але будь-яка інформація про кутові корпуси в інших оболонках вітається.


Я думаю, що це не має ніякого значення, якщо він знаходиться на одній лінії, як ти маєш його у своїй функції. Призначення не потребують цитування. Дивіться mpi-sb.mpg.de/departments/rg1/teaching/unixffb-ss98/…
jirib

Відповіді:


41

Котирування необхідні export foo="$var"або local foo="$var"(або readonly, typeset, declareта інші змінні оголошенні команд ) в:

  • dash
  • shз NetBSD (також на основі Almquist оболонки).
  • shЗ FreeBSD 9.2 або старше (див змін до 9.3 )
  • yash
  • zshз версіями до 5.1 в kshабо shемуляції (або для того, export var="$(cmd)"де zshбуло б виконано розділення слів в іншому випадку (не глобулювання)).

Оскільки інакше розширення змінної буде підлягати розщепленню слів та / або генерації імен файлів, як у будь-якому аргументі будь-якої іншої команди.

І вони не потрібні:

  • bash
  • ksh (усі реалізації)
  • shз FreeBSD 9.3 або більш пізньої версії
  • на основі попелу sh(з 2005 р.)
  • zsh

У zsh, split + glob ніколи не робиться при розширенні параметрів, якщо тільки не відбувається shабо kshемуляція, але роздвоєння (не glob) робиться після заміни команди. Оскільки версія 5.1, export/ localта інші команди декларації стали подвійними ключовими словами / вбудованими командами, як і в інших оболонках вище, що означає, що цитування не є необхідним, навіть в sh/ kshемуляції та навіть для заміни команд.

Існують особливі випадки, коли цитування потрібно навіть у цих оболонках, хоча так:

a="b=some value"
export "$a"

Або загалом, якщо що-небудь, що залишилося від =(включаючи =), цитується або є результатом якогось розширення (наприклад export 'foo'="$var", export foo\="$var"або export foo$((n+=1))="$var"(що $((...))також має бути цитується фактично) ...). Або іншими словами, коли аргумент exportне буде дійсним призначенням змінної, якщо він написаний без знака export.

Якщо export/ localім'я команди сам котируються (навіть в частині , як "export" a="$b", 'ex'port a="$b", \export a="$b"або навіть ""export a="$b"), лапки навколо $bпотрібні тільки в AT & T kshі mksh.

Якщо export/ localабо якась її частина є результатом деякого розширення (наприклад, у cmd=export; "$cmd" a="$b"або навіть export$(:) a="$b") або в подібних речах dryrun=; $dryrun export a="$b"), то лапки потрібні в кожній оболонці.

У випадку з > /dev/null export a="$b"котируваннями потрібні pdkshдеякі та його похідні.

Для command export a="$b", лапки необхідні в будь-який оболонці , але mkshі ksh93(з тими ж застереженнями по приводу commandі exportне є результатом якого - то розширення).

Вони не потрібні в жодній оболонці, коли пишеться:

foo=$var export foo

(цей синтаксис також сумісний з оболонкою Bourne, але в останніх версіях zsh, працює лише під час введення sh/ kshемуляції).

(зауважте, var=value local varйого не слід використовувати, оскільки поведінка різниться в оболонках).

Також зауважте, що використання exportз призначенням також означає, що статус виходу cmdв export var="$(cmd)". Зробити це так, як export var; var=$(cmd)немає цієї проблеми.

Також остерігайтеся цього особливого випадку bash:

$ bash -c 'IFS=; export a="$*"; echo "$a"' bash a b
ab
$ bash -c 'IFS=; export a=$*; echo "$a"' bash a b
a b

Моя порада буде завжди цитувати.


3
Зверніть увагу , що в zshлапках будуть необхідні для local foo="$(cmd)"тому wordsplitting (але не ім'я файлу покоління) буде виконуватися для некотируваних підстановки команд (але не для некотируваних розширень параметрів), якщо KSH_TYPESETне включене, і в цьому випадку лапки НЕ потрібна. Мати сенс? Ні? Тоді завжди цитуйте все, якщо ви точно не знаєте, що робите.
Метт

2
@Matt, я люблю твій висновок. : D Дивно, що більшість того, що я дізнався про сценарії оболонок, походили саме з цієї ставки обміну, так що я не усвідомлював, що завжди цитувати ваші змінні не є загальним знанням серед сценаристів. Я знаходжу, що у мене є багато придумувань, щоб зробити існуючі виробничі сценарії, написані людьми, які не цитували і не знали, що саме роблять ....
Wildcard

3

Я загалом цитую будь-яке використання змінних, де можуть бути символи, такі як пробіли. Інакше у вас виникнуть такі проблеми:

#!/bin/bash

bar="hi bye"

function foo {
  local myvar=${bar}
  printf "%s\n" $myvar
  printf "%s\n" "$myvar"
}

foo

Використання змінної у призначенні, як видається, не потребує лапок, але коли ви перейдете до її використання, як, наприклад, у printfпотрібному вам цитуванні:

  printf "%s\n" "$myvar"

ПРИМІТКА. Пам'ятайте, що змінна $IFS- це те, що регулює, якими є символи роздільника.

IFS    The  Internal  Field  Separator that is used for word splitting after 
       expansion and to split lines into words with the read builtin command. 
       The default value is ``<space><tab><newline>''.

Приклад

Увімкнувши налагодження в Bash, ми можемо бачити, що відбувається за кадром.

$ bash -x cmd.bash 
+ bar='hi bye'
+ foo
+ local 'myvar=hi bye'
+ printf '%s\n' hi bye
hi
bye
+ printf '%s\n' 'hi bye'
hi bye

У вищесказаному ми можемо побачити, що змінна $barбула передана штрафом, $myvarале тоді, коли ми перейшли до використання, $myvarнам довелося визначити вміст, $myvarколи ми перейшли до її використання.


2
Слово розщеплення не єдина проблема , з некотируваних змінними, ви повинні розглянути покоління файлу (він же підстановка) , а також (хоча це (обидва) не застосовується в призначенні змінних і bashі kshв local/ typeset... Спеціальні модулі).
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.