Мы обычно используем $@
для представления всех аргументов, кроме $ 0. Однако я не знаю, что такое структура данных $@
.
Почему $*
при включении в двойные кавычки он ведет себя иначе , может кто-нибудь дать мне объяснение на уровне переводчика?
Его можно повторять в цикле for, поэтому он выглядит как массив. Тем не менее, он также может быть полностью повторен с простым echo $@
, если это массив, будет показан только первый элемент. Из-за ограничений оболочки я не могу написать больше экспериментального кода для его выполнения.
Разница между этим постом : этот пост показывает, как $@
ведет себя иначе, чем $*
. Но меня интересует тип данных $@
. Shell как интерпретирующий язык, такой как Python, должен представлять данные в соответствии с рядом фундаментальных типов. Или, другими словами, я хочу знать, как $ @ хранится в памяти компьютера.
Это строка, многострочная строка или массив?
Если это уникальный тип данных, возможно ли определить пользовательскую переменную как экземпляр этого типа?
printf '%s\n' "$@"
иprintf '%s\n' "$*"
.echo
Утилита просто выводит свои аргументы, независимо от того , если они являются один или много. Оба являются массивами (строк), но они ведут себя по-разному, если заключены в двойные кавычки. Если бы любая из них была многострочной строкой, то они не смогли бы хранить многострочные строки (что они могут). Непонятно, какую проблему вы пытаетесь решить.@var
переменная в Perl, с точки зрения ее базового хранилища. С точки зрения обычной Perl-программы это не имеет большого значения, кроме того, что она доступна в виде массива / списка (и того факта, что существуют контексты, в которых ожидается список).Ответы:
Это началось как взломать оболочку Борна. В оболочке Bourne разделение слов IFS было выполнено (после токенизации) для всех слов в контексте списка (аргументы командной строки или слова, в которых
for
циклы циклы). Если у тебя есть:Это вторая линия будет tokenised в 3 -х слов,
$var
будет расширен, и раскол + Glob будет сделано на всех трех слов, так что вы в конечном итоге работаетed
сt
,f
,le.txt
,f
, вle2.txt
качестве аргументов.Цитирование частей этого предотвратит разделение + глобус. Оболочка Bourne изначально помнила, какие символы были заключены в кавычки, установив для них внутренний 8-й бит (это изменилось позже, когда Unix стал чистым 8-битным, но оболочка все еще сделала нечто похожее, чтобы запомнить, какой байт был заключен в кавычки).
Оба
$*
и$@
были объединением позиционных параметров с пробелом между ними. Но была особая обработка,$@
когда внутри двойных кавычек. Если$1
содержитсяfoo bar
и$2
содержитсяbaz
,"$@"
будет расширен до:(с
^
символом выше, указывающим, для какого из символов установлен 8-й бит). Где первый пробел был заключен в кавычки (был установлен 8-й бит), но не второй (тот, который был добавлен между словами).И это разделение IFS, которое заботится о разделении аргументов (при условии, что символ пробела находится в том виде,
$IFS
как он есть по умолчанию). Это похоже на то, как$*
в его предшественнике была расширена оболочка Mashey (сама основанная на оболочке Thomson, тогда как оболочка Bourne была написана с нуля).Это объясняет , почему в Bourne оболочки вначале
"$@"
будет расширяться в пустую строку вместо ничего вообще , когда список позиционных параметров был пуст (вы должны были работать на него с${1+"$@"}
), поэтому он не держать пустые позиционные параметры и почему"$@"
Didn не работает, когда$IFS
не содержит пробела.Намерение состояло в том, чтобы быть в состоянии передать список аргументов дословно другой команде, но это не работало должным образом для пустого списка, для пустых элементов или когда
$IFS
не было места (первые две проблемы были в конечном счете исправлены в более поздних версиях ).Оболочка Korn (на которой основана спецификация POSIX) изменила это поведение несколькими способами:
edit
илиfile.txt
в примере выше)$*
и$@
соединяются с первым символом$IFS
или пробелом, когда$IFS
он пуст, за исключением того, что для заключенных в кавычки"$@"
этот соединитель не заключен в кавычки , как в оболочке Bourne, а для заключенных в кавычки,"$*"
когдаIFS
он пуст, позиционные параметры добавляются без разделителя.${array[@]}
${array[*]}
напоминает Борна$*
и$@
но начиная с Indice 0 вместо 1, и редкими (больше как ассоциативные массивы) , что означает на$@
самом деле нельзя рассматривать как массив КШ (сравните сcsh
/rc
/zsh
/fish
/ ,yash
где$argv
/$*
нормальны массивы)."$@"
когда$#
0 - теперь расширяется в пустую строку вместо пустой,"$@"
работает, когда$IFS
не содержит пробелов, кроме случаев, когдаIFS
пусто.$*
Без кавычек без подстановочных знаков расширяется до одного аргумента (где позиционные параметры объединяются с пробелом), когда$IFS
он пуст.ksh93 исправил оставшиеся проблемы выше. В ksh93
$*
и$@
расширяется до списка позиционных параметров, разделенных независимо от значения$IFS
, и затем далее split + globbed + brace-раскрытый в контекстах списка,$*
соединенный с первым байтом (не символом)$IFS
,"$@"
в контекстах списка расширяется до списка позиционных параметров, независимо от значения$IFS
. В не-списке контекста, как вvar=$@
,$@
объединяется с пробелом независимо от значения$IFS
.bash
Массивы разработаны после ksh. Различия:$IFS
вместо байта$*
без кавычек в контексте без списка, когда$IFS
пусто.Хотя спецификация POSIX раньше была довольно расплывчатой, теперь она более или менее определяет поведение bash.
Это отличается от обычных массивов в том
ksh
или иномbash
:"${@:0}"
что включает$0
(не позиционный параметр, а в функциях дает вам имя функции или нет, в зависимости от оболочки и способа определения функции)).shift
может быть использован.В
zsh
илиyash
где массивах являются нормальными массивами (не редко, индексы начинаются в одном , как и во всех других оболочках , но КШ / Баше),$*
рассматриваются как нормальный массив.zsh
имеет$argv
псевдоним для этого (для совместимости сcsh
).$*
аналогично$argv
или${argv[*]}
(аргументы, объединенные с первым символом,$IFS
но все еще выделенные в контекстах списка)."$@"
как"${argv[@]}"
или"${*[@]}"}
подвергается специальной обработке в стиле Korn.источник
Это специальный параметр, который распространяется на значения позиционных параметров ... Но это придирчиво к терминологии.
Мы можем рассматривать позиционные параметры как части
$@
, поэтому он имеет ряд различных элементов ($1
,$2
...), к которым можно обращаться независимо и которые называются последовательными натуральными числами. Это делает его чем-то, что обычно называют массивом.Хотя синтаксис немного странный и даже ограниченный. Нет способа изменить отдельный элемент массива по отдельности. Вместо этого все должно быть установлено сразу. (Вы можете использовать,
set -- "$@" foo
чтобы добавить значение илиset -- "${@:1:2}" foo "${@:3}"
добавить значение в середине. Но вы в обоих случаях должны выписать весь результирующий список.)Потому что они определены, чтобы вести себя по-другому.
Если вы имеете в виду тот факт, что
a=(foo bar asdf); echo $a
будет выводиться простоfoo
, то это в основном причуды синтаксиса оболочки и тот факт, что именованные массивы в стиле ksh были созданы позже, чем позиционные параметры и$@
. Plain$a
- это то же самое,${a[0]}
что и обратно-совместимое значение одного скалярного значения, независимо от того,a
является ли он массивом или простой скалярной переменной.@
Знак со ссылкой на весь список был повторно с именованными массивами в том , что"${a[@]}"
это способ получить весь список. По сравнению с именованными массивами$@
ненужные скобки и скобки и имя просто пропускаются.Это зависит от реализации, вам придется искать исходный код любой конкретной оболочки, которая вас интересует.
Массив, в основном. Хотя он отличается от именованных массивов в стиле ksh, поскольку они могут иметь произвольные неотрицательные целые числа в качестве индексов, а не только последовательные, как в случае с
$@
. (То есть именованный массив может быть разреженным и иметь, например, индексы1
,3
а также4
с0
и2
без. Это невозможно с позиционными параметрами.)Это не единственная строка, поскольку она может быть расширена до отдельных элементов, и вызов строк элементов также не является правильным, поскольку любая регулярная переменная или один из позиционных параметров (элементов
$@
) также могут содержать символы новой строки.Но именованные массивы в любом случае, вероятно, более полезны.
источник
$@
не структура данных, это одна из немногих функций / операторов для расширения структуры данных позиционных параметров.