Подстановка команд в кавычках не может быть использована для вызова переменной

Команда pasteобъединяет столбцы вместе. Так, например, если у нас есть эти 3 файла, вставка создаст хороший результат:

$ cat file_1.txt
1a
1b
1c

$ cat file_2.txt
2a
2b
2c

$ cat file_3.txt
3a
3b
3c

$ paste -d, file_1.txt file_2.txt file_3.txt
1a,2a,3a
1b,2b,3b
1c,2c,3c

Итак, теперь вопрос в том, как привести файлы в порядок. Мы можем обмануть и позволить lsсделать за нас работу

$ ls     
file_1.txt   file_13.txt  file_17.txt  file_20.txt  file_6.txt
file_10.txt  file_14.txt  file_18.txt  file_3.txt   file_7.txt
file_11.txt  file_15.txt  file_19.txt  file_4.txt   file_8.txt
file_12.txt  file_16.txt  file_2.txt   file_5.txt   file_9.txt

$ ls -v
file_1.txt  file_5.txt  file_9.txt   file_13.txt  file_17.txt
file_2.txt  file_6.txt  file_10.txt  file_14.txt  file_18.txt
file_3.txt  file_7.txt  file_11.txt  file_15.txt  file_19.txt
file_4.txt  file_8.txt  file_12.txt  file_16.txt  file_20.txt

$ paste -d, $(ls -v file_*.txt)
1a,2a,3a,4a,5a,6a,7a,8a,9a,10a,11a,12a,13a,14a,15a,16a,17a,18a,19a,20a
1b,2b,3b,4b,5b,6b,7b,8b,9b,10b,11b,12b,13b,14b,15b,16b,17b,18b,19b,20b
1c,2c,3c,4c,5c,6c,7c,8c,9c,10c,11c,12c,13c,14c,15c,16c,17c,18c,19c,20c

Имейте в виду, что синтаксический анализ lsобычно плох. Если есть какие-либо неожиданные имена файлов или нечетные символы (, например, пробел, подстановка ), это может привести к поломке вашего скрипта. Но если вы уверены, что имена файлов «хорошие», тогда это сработает.

4
23.07.2020, 00:16
3 ответа

Пахнет анти -шаблоном (*). Многие оболочки имеют массивы/словари, индексированные строкой -. В ksh93(, где этот синтаксис взят из ), bashилиzsh:

typeset -A dictionary
x="keyX"
y="keyY"
dictionary[keyX]="valueX"
dictionary[$y]="valueY"

printf '%s\n' "${dictionary[$x]}"
printf '%s\n' "${dictionary[keyY]}"

(*)Ничего общего с Linux как таковым. Переменная -имя -в -переменная -— это очень общий "анти--шаблон" , то, что не следует делать, и если вы считаете, что вам нужно это проблема с вашим дизайном(XY проблема)? Большинство случаев использования переменной -имени -в -переменной -лучше заменить словарем, если он существует.

8
18.03.2021, 23:18

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

  1. считывает свой ввод;

  2. разбивает ввод на токены :слова и операторы(распознавание токенов);

    • на этом шагекаждый раз, когда он встречает без кавычек$(или `), он рекурсивно определяет тип расширения и токен, который нужно раскрыть, считывая все необходимые входные данные;
  3. разбирает ввод на простые команды и составные команды;

  4. выполняет различные расширения(отдельно )для разных частей каждой команды, в результате чего получается список имен путей и полей, которые следует рассматривать как команду и аргументы;

  5. выполняет перенаправление и удаляет операторы перенаправления и их операнды из списка параметров;

  6. выполняет встроенную -функцию, исполняемый файл или скрипт;

  7. дополнительно ожидает завершения команды и собирает статус выхода.

При синтаксическом анализе echo "\$$(echo $var2)"оболочка обнаруживает два расширения (шаг 2 ):подстановку команды в двойных -кавычках $(echo $var2)и расширение параметра без кавычек $var2. Экранированный $в \$воспринимается как буквальный знак доллара, потому что -в двойных кавычках \сохраняет свою роль escape-символа , когда за ним следует $.

На более поздних стадиях дальнейшего обнаружения расширений не происходит. В частности, дальнейший синтаксический анализ результата раскрытия, выполненного на шаге 4("\$$(echo $var2)""\$$(echo variable)""\$variable"$variable), который мог бы обнаружить символы запуска раскрытия -, не выполняется.

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

В расширении стандартного параметра , простейшей формой которого является ${parameter}, спецификацияparameterможет быть только именем переменной, позиционным параметром или специальным параметром (, см. определение "параметра"). Строго говоря,расширения параметров не могут быть вложенными (выражение расширения разрешено только какwordв различных формах${parameter<symbols>[word]}).

Вы можете легко проверить, что, за исключением оболочки Z , ${${foo}}не является допустимым выражением и что $$расширяется до PID оболочки (, таким образом, $fooрасширяется до значения foo, $$fooрасширяется до конкатенации PID оболочки и литерала "foo", $$$fooрасширяется до конкатенации PID оболочки и значения foo,... ).

5
18.03.2021, 23:18

В дополнение к косвенному раскрытию переменных, в bash (, начиная с версии 4.3 ), вы можете использовать ссылку на имя

declare -n var2="variable"  # "var2" is a _reference_ to "variable"

variable="Something"
echo "$var2"     # => Something

variable="something else"
echo "$var2"     # => something else

unset variable
echo "$var2"     # => ""

Я не знаю, как это реализовано, но это интересный момент :вы можете узнать, на что ссылается nameref, используя косвенность:

echo ${!var2}    # => variable
1
18.03.2021, 23:18

Теги

Похожие вопросы