Расширение переменной оболочки и влияние glob и split на него

18

Этот пост на самом деле содержит два отдельных вопроса, но я думаю, что их объединение даст больше контекста. Я прошел через этот вопрос о кавычках вокруг переменных, но я не совсем понимаю, что означает расширение переменных . Итак, мой первый вопрос:

  1. Что говорят расширения переменных в unix / linux?

Вторая часть моего вопроса относится к следующим терминам:

  1. Glob
  2. Трещина

Что означают вышеизложенные и как они влияют на расширение переменных? Ответ на оригинальный вопрос упоминает следующее:

Думайте об отсутствии кавычек (в контексте списка) как оператора split + glob.

Как будто echo $ test был echo glob (split ("$ test")).

Я не смог найти никаких ответов, которые бы непосредственно касались концепции глобализации и расщепления, а скорее использовали эти термины непосредственно при ответе на другие вопросы, такие как этот недавний .

Компьютерщик
источник

Ответы:

15

Расширение переменной (стандартный термин - расширение параметра , и его также иногда называют заменой переменной ) в основном означает замену переменной ее значением. Точнее, это означает замену $VARIABLEконструкции (или ${VARIABLE}( ${VARIABLE#TEXT}или) других конструкций) каким-либо другим текстом, который построен из значения переменной. Этот другой текст является расширением переменной.

Процесс расширения идет следующим образом. (Я обсуждаю только общий случай, некоторые настройки оболочки и расширения изменяют поведение.)

  1. Возьмите значение переменной, которая является строкой. Если переменная не определена, используйте пустую строку.
  2. Если конструкция включает преобразование, примените его. Например, если конструкция имеет значение ${VARIABLE#TEXT}, а значение переменной начинается с TEXT, удалите TEXTиз начала значения.
  3. Если контекст требует отдельного слова (например, в двойных кавычках, или в правой части назначения, или внутри документа here), остановитесь здесь. В противном случае перейдите к следующим шагам.
  4. Разделите значение на отдельные слова в каждой последовательности пробелов. (Переменная IFSможет быть изменена для разделения на символы, отличные от пробелов.) Таким образом, результатом является уже не строка, а список строк. Этот список может быть пустым, если значение содержит только пробелы.
  5. Считайте каждый элемент списка шаблоном имени файла, то есть глобусом . Если шаблон соответствует некоторым файлам, он заменяется списком совпадающих имен файлов, в противном случае он остается один.

Например, предположим, что переменная fooсодержит, a* b* c*а текущий каталог содержит файлы bar, bazи paz. Затем ${foo#??}расширяется следующим образом:

  1. Значением переменной является строка из 8 символов a* b* c*.
  2. #??означает удаление первых двух символов, в результате  b* c*получается строка из 6 символов (с начальным пробелом).
  3. Если расширение находится в контексте списка (т.е. не в двойных кавычках или другом подобном контексте), продолжайте.
  4. Разбейте строку на слова, разделенные пробелами, и получите список из двух строк: b*и c*.
  5. Строка b*, интерпретируемая как шаблон, соответствует двум файлам: barи baz. Строка не c*соответствует ни одному файлу, поэтому она остается одна. Результатом является список из трех строк: bar, baz, c*.

Например, echo ${foo#??}печатает bar baz c*(команда echoобъединяет свои аргументы с пробелом между ними).

Для более подробной информации смотрите:

Жиль "ТАК - прекрати быть злым"
источник
2
Обратите внимание , что это называется расширением параметра , поскольку это относится к переменным ( $var) и другим типам параметров , такие как $1, $#, $?, $-...
Stéphane Chazelas
12

Glob / раскол

Я сначала возьму шар / сплит. @ Ответ Стефана, на который вы ссылаетесь, использует эти термины в общем смысле. Это не настоящие команды или что-то в этом роде, а просто псевдо-операции.

Это split("$test")разделит содержимое «$ test» на «массив» элементов.

Затем glob(...)он позаботится о расширении любого из этих элементов, которые содержат символы-заглушки оболочки, такие как *или диапазоны [1-2].

пример

Скажем, наша строка $testвыглядит следующим образом.

$ test="afile[1-2] afile[3-5]"

Также допустим, что у нас есть каталог с некоторыми файлами.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Теперь, если мы попытаемся отобразить его без кавычек, вы должны заметить, что наша строка разделена пробелами, а затем все символы-заглушки расширились.

$ echo $test
afile1 afile2 afile3 afile4 afile5

Однако, если бы мы указали переменную в кавычках, когда передавали ее в качестве аргумента, echoмы получили бы исходную буквенную строку.

$ echo "$test"
afile[1-2] afile[3-5]

переменное расширение

Термин «расширение переменной» предназначен для обозначения основной операции, выполняемой оболочкой в ​​рамках основных операций. Оболочка отвечает за синтаксический анализ входных данных, а затем за выполнение этих входных данных, если они считаются синтаксически правильными.

В нашем предыдущем примере. Когда переменная $testбыла представлена ​​без echoкавычек, мы говорили оболочке идти дальше, разбивать эти аргументы и затем их выводить.

Когда оно было заключено в кавычки, мы фактически отключали эту функцию тем, что когда-либо было изменено в двойных кавычках.

пример

Вот несколько дополнительных примеров срыва и расщепления.

шар / расщепление происходит автоматически

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

Glob / расщепление отключено через двойные кавычки

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}
SLM
источник
Я не знал, диапазоны также работали в обратном порядке.
Джо