Что такое (именно) "контекст списка" (и "контекст строки")?

В основном это сводится к следующему:

  1. Откройте ~ / .config / fish / config.fish в вашем любимом редакторе. Если его еще нет, он сделает это за вас. (Но не su .)
  2. Добавьте все псевдонимы, которые хотите. Он сохранит их и всегда будет загружать, потому что это, по-видимому, версия bashrc для Fish.
  3. Спаси его, детка!
  4. Наслаждайтесь.
3
16.07.2017, 03:40
3 ответа

В стандартном языке оболочки нет такого понятия. Нет никаких «контекстов», только шаги расширения.

Цитаты сначала идентифицируются при токенизации, которая производит слова. Они склеивают слова так, что abc"spaces here"xyzсоставляет одно «слово».

Важно понимать, что кавычки сохраняются на последующих шагах раскрытия, а исходные кавычки отличаются от кавычек, которые могут возникнуть в результате раскрытия.

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

Расширение имени пути ("подстановка" )происходит после этого разбиения. Сохраненные кавычки предотвращают это :операторы подстановки внутри кавычек не распознаются.

Наконец, кавычки удаляются на последнем этапе, который называется «удаление кавычек». Конечно,только оригинальные кавычки!

POSIX хорошо представляет процесс в понятной форме; попытки демистифицировать его с помощью посторонних концепций (, которые могут ввести в заблуждение ), только запутают понимание.

Люди, использующие ad hoc концепции, такие как «контекст списка», должны формализовать свое мышление до такой степени, чтобы оно могло предоставить полную альтернативную спецификацию для всей обработки, которая эквивалентна (производящей одно и то же. результаты ). И затем, избегайте смешения концепций между параллельными планами :, используйте то или иное объяснение. «Контекст списка» или «контекст строки» имеет смысл в теории расширения оболочки, в которой они четко определены, а этапы обработки организованы вокруг этих концепций.

Если я угадал, то "контекст списка" относится к идее, что оболочка работает со списком размеченных слов, таким как список из двух -слов {foo} {abc" x "def}. Кавычки не являются частью второго слова :, его содержание на самом деле abc x def; это семантические кавычки, которые предотвращают разделение на пробелы. Внутри этих кавычек у нас есть «контекст строки».

Однако возможной реализацией этих шагов расширения является не фактическое наличие кавычек, которые идентифицируются как исходные кавычки, а некоторая структура данных списка, так что {foo} {abc" x "def}является, скажем, список списков, в которых части в кавычках идентифицируются как различные типы узлов (, а кавычки отсутствуют ). Используя нотацию Лиспа, это может быть:

(("foo") ;; one-element word
 ("abc" (:dq-str " x ") "def")) ;; three-element word

Узлы без метки — это обычный текст, :dq-str— область с двойными -кавычками. Другой тип может быть :sq-strдля одного элемента в кавычках.

Расширение может пройти по этой структуре, а затем выполнять разные действия в зависимости от того, просматривает ли оно строковый объект, :dq-strвыражение или что-то еще.Расширение файла и разделение полей будут подавлены как в :dq-str, так и в :sq-str. Но расширение параметра происходит внутри :dq-str. «Удаление кавычек» тогда будет соответствовать последнему проходу, который берет части и связывает строки, сглаживая внутреннюю структуру списка и теряя символы, указывающие тип, что приводит к:

("foo"
 "abc x def") ;; plain string list, usable as command arguments

Теперь обратите внимание, что во втором пункте мы имеем ("abc" (:dq-str " x ") "def"). Первый и последний элементы развернуты :, они являются прямыми элементами списка, и поэтому мы можем сказать, что они находятся в «контексте списка». Принимая во внимание, что средний " x "заключен в выражение :dq-str, так что это «(контекст строки с двойными кавычками )».

Что означает «список» в «контексте списка», можно только догадываться без четко определенной модели, такой как эта. Это главный список слов? Или список фрагментов, представляющих одно слово?

12
27.01.2020, 21:07

Формулировки «контекст списка» и «контекст строки» пришли из Perl, но аналогичные концепции применимы к языку оболочки. Обратите внимание, что это похожие понятия :виды контекстов и последствия типа контекста различны.

Слово контекст является техническим термином в семантике языка программирования. Его точное значение привязано к конкретной семантической формализации, которая выходит за рамки данного ответа. Когнитивное значение — это природа окружения фрагмента кода. Например, заявление о том, что фрагмент кода $fooимеет разное значение в разных контекстах, означает, что поведение программы, содержащей $foo, зависит от природы того, что происходит вокруг этого вхождения $fooв программе.

Семантика оболочки довольно сложна. Он не подпадает под традиционные категории, которые вы найдете во вводных учебниках по языкам программирования. Выполнение программы оболочки можно разбить на две фазы (обратите внимание, что это способ представить семантику,это не означает, что интерпретатор оболочки должен быть разбит таким образом):

  1. Этап синтаксического анализа превращает строку (содержимого исходного файла или аргумента в-c)в абстрактное синтаксическое дерево. В спецификации POSIX это соответствует шагам 2 и 3 (распознавание и разбор токена ). Спецификация POSIX определяет правила грамматики , которые описывают форму дерева. Обратите внимание, что это не контекстная -свободная грамматика – представление основано на обычном представлении контекстных -свободных грамматик, но аннотации «применить правило N » делают его более сложным математическим объект.

  2. Этап выполнения выполняет некоторую оценку узлов дерева и вызывает внешние команды. В спецификации POSIX это соответствует шагам 4–7 (раскрытие, перенаправление, выполнение команды и ожидание ).

Расширение — это процесс, который применяется к определенному типу узла в абстрактном синтаксическом дереве, который POSIX называет WORDи который обычно называют «словом». Его можно разделить на две группы.

  1. Первая группа расширений состоит, в терминологии POSIX, из расширения с тильдой (, например. ~foo/home/foo), расширение параметра(напр. $foobar, если значение fooравно bar), подстановка команды (, например. $(foo)bar, если выводом команды fooявляетсяbarарифметическое расширение (, например. $((2+2))4). Эта первая группа расширений выполняется для каждого слова, за исключением символов, которые «заключены в кавычки» в силу того, что они заключены в одинарные кавычки или им предшествует обратная косая черта. Результатом этой группы расширений является приблизительно строка с аннотациями (. Я объясню приближение ниже ).

  2. Вторая группа расширений состоит из разделения полей и расширения пути (, широко известного как «генерация имени файла» или «подстановка» ). Эта группа расширений превращает аннотированную строку в список строк. Эта группа расширений выполняется на подмножестве мест, где выполняется первая группа :не выполняется на частях слов, заключенных в двойные кавычки, и вообще не выполняется, если слово в определенных позициях в абстрактном синтаксическом дереве . Именно здесь контексты списка и строки вступают в :в определенных контекстах, т.е. для определенных классов позиций в абстрактном синтаксическом дереве выполняется вторая группа расширений. Это контексты списка , названные так потому, что результатом процесса раскрытия является список (строк ). В других контекстах, называемых строковыми контекстами , вторая группа расширений не выполняется, и результатом процесса раскрытия является одна строка.

POSIX описывает удаление кавычек как последнюю стадию расширения. Это один из способов объяснить заключение в кавычки, когда все раскрытия перед разделением полей определяются как преобразование строки в строку. Например, для слова '$foo'$bar\$quxпри условии, что значение переменной barравно value, расширение параметра превращает его в '$foo'value\$qux, а другие первые -групповые расширения оставляют строку неизменной. Удаление кавычек, наконец, удаляет кавычки, чтобы получить $foovalue$qux.

Представление с удалением кавычек требует выполнения сопоставления кавычек на каждом этапе. Презентация, которая проще для понимания и реализации и дает тот же конечный результат, заключается в выполнении этапа расшифровки кавычек, результатом которого является список частей. Каждая часть аннотируется, чтобы помнить, цитировалась ли она. Например, '$foo'$bar\$quxзаключает в кавычки следующие части :, заключает в кавычки $foo, расширение переменной barбез кавычек,цитируемый $, голый q, голый u, голый x. (Различие между «кавычками» и «голыми» необходимо для таких вещей, как определение присвоений и принятие решения о том, следует ли расширять псевдонимы. )Второй этап раскрытия -происходит только для частей без кавычек в контексте списка.

POSIX указывает, происходит ли вторая группа расширений, путем явного перечисления этапов расширения. Например, «Каждое назначение переменной должно быть расширено для расширения с помощью тильды, расширения параметра, подстановки команд, арифметического расширения и удаления кавычек перед присвоением значения». Более простой способ сформулировать это так: происходят только первые раскрытия группы -, т. е. это присваивание является строковым контекстом. Контекста всего два, потому что есть только два набора правил выполнения раскрытий :либо выполняется вся первая группа (контекст строки ), либо обе группы выполняются по порядку (контекст списка ).

(На самом деле, чтобы быть полным, существует третий вид контекста,:caseконтекст шаблона. В шаблоне caseвыполняются только раскрытия первой -группы (, как и в строковом контексте ), но часть второй группы расширений имеет значение — символы подстановки без кавычек являются подстановочными знаками для сопоставления строк.)

Определение языка определяет, какие контексты являются контекстами списка, а какие строковыми контекстами. В принципе, это может быть произвольно. Однако за этим стоит интуиция :в тех местах, где грамматика ожидает список из WORDтокенов, над этими токенами выполняется второе -групповое расширение, тогда как в местах, где грамматика требует одиночный WORD, второй -Расширение группы не выполняется. Простой способ объяснить это так: там, где грамматика ожидает список, это контекст списка, а там, где грамматика ожидает одну строку, это строковый контекст.

0
27.01.2020, 21:07

Поскольку большинство случаев, на которые вы ссылаетесь, принадлежат мне, я чувствую, что должен дать ответ здесь, хотя в основном я буду перефразировать @Gilles.

Я использовал контекст списка и скалярный/не -контекст списка(лучше, чем строковый контекст , что может сбивать с толку, если его не понимать как не -list context )десятки раз, начиная с 2004 года вusenet или unix.SE большую часть времени в статьях, обсуждающих влияние оставления расширений без кавычек в Bourne -как снаряды. Я не помню, чтобы кто-то просил разъяснений относительно того, что я имел в виду под этим раньше (Я действительно часто пытаюсь привести несколько примеров таких контекстов для иллюстрации)

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

Это не официальная терминология , хотя очевидно, что она основана на perlофициальной (терминологии )документации. Я не могу сказать, использовали ли другие люди их в контексте оболочек Unix до меня (, хотя очень вероятно, что они это делали ), но, безусловно, с тех пор. Я не претендую на право собственности на это.

list context(по крайней мере, когда я использовал его в контекстах, в которых я его использовал )просто означает контексты, в которых оболочка ожидает любое количество элементов. В то время как скалярный/не -список/строковый контекст будет там, где ожидается только один (или одна строка/скаляр, если хотите ), как в perl. В большинстве оболочек, подобных Bourne -, эти контексты списков:

  • аргументы простой команды (как вecho elements)
  • for i in elements
  • array=(elements)(и вариант с+=)

Некоторые снаряды больше похожи на:

  • cmd < elementsв zsh, что делает что-то похожее наcat -- elements | cmd(как в nl < *.txt, nl < {foo,bar}.txt, ноnl < foo.txt < bar.txt).
  • cmd > elements(и варианты с >|>>...)в zsh, что делает что-то похожее наcmd | tee -- elements
  • elements() { code; }в zshопределить одну или несколько функций одновременно (или ничего, если элементы разрешаются в пустой список (хотя литерал () { echo x; }является анонимной функцией )).
  • compound=(foo=(elements) elements)или matrix=((elements) (elements))и так далее в ksh93.
  • и т. д.

В этих контекстах, как правило, подстановочные знаки расширяются, и вам нужно указать свои расширения в кавычках, если вы не хотите, чтобы split+glob (или просто пустое удаление -с помощью zsh, если вы не включили shwordsplit/ globsubstsh -параметры совместимости ), применяемые к ним.

Например, если заменить элементы на *.txtв приведенных выше примерах, *.txtбудет расширен до списка файлов txt в текущем каталоге.

Если вы ищете эквивалент в спецификации POSIX, ищите контексты, в которых раскрываются универсальные символы. POSIX по крайней мере в одном случае ссылается на это как на контекст, в котором будет выполняться разделение полей(формулировка, которая была фактически изменена после того, как я поднял вопросы с предыдущей формулировкой перед группой Остина). Конечно, эта формулировка не очень полезна для ответа на вопросы о , где выполняется расщепление поля .

скалярные контексты будут другими контекстами.

В

scalar=*.txt
case *.txt in...
[[ -f *.txt ]]

*.txtне может быть расширен, потому что оболочка ожидает только одну строку .

В качестве предостережения/ограничения эти термины не совсем точно отражают то, что происходит в cmd > *, cmd > ~(N)patternили a=(); b=; c=(a b); d=*; IFS=:; e=a:b; cmd 1> "${a[@]}" 2> $b 3> "${c[@]}" 4> $d 5> $eв таких оболочках, как bash/ yash(, когда они не в режиме POSIX ),ksh88(с использованием set -Aвместо var=(...)синтаксиса )илиksh93(только при взаимодействии с некоторым ), где его можно рассматривать как другой контекст списка , за исключением того, что только список с одним ожидается элемент (с разбиением и подстановкой для некоторых ).

6
27.01.2020, 21:07

Теги

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