При использовании хинду источника и уже в хинду среде app-admin/eselect инструмент поможет Вам сделать это:
eselect kernel list
и
eselect kernel set
И если Вы не знакомы с установкой ядра genkernel, может быть очень полезным. Вы могли бы хотеть использовать - конфигурация = и - menuconfig, который не документируется в HandBook (HandBook является просто формой пошагового руководства перспектива некоторого dev, много инструментов, которые он упомянул, недооценены новыми читателями).
Во-первых, я бы сказал, что это неправильный способ решения проблемы. Это немного похоже на выражение " вы не должны убивать людей, потому что иначе вы попадете в тюрьму ».
Точно так же вы не заключаете переменную в кавычки, потому что в противном случае вы вносите уязвимости в системе безопасности. Вы цитируете переменные , потому что это неправильно (но если страх тюрьмы может помочь, почему бы и нет).
Небольшое резюме для тех, кто только что запрыгнул в поезд.
В большинстве оболочек, оставление раскрытия переменной без кавычек (хотя
это (и остальная часть этого ответа) также применяется к подстановке команды
( `...`
или $ (...)
) и арифметическое расширение ( $ ((...))
или $ [...]
)) имеет очень особое значение
.Лучше всего описать это как
вызов некоторого неявного оператора split + glob .
cmd $var
на другом языке будет выглядеть примерно так:
cmd(glob(split($var)))
$ var
сначала разбивается на список слов в соответствии со сложными
правилами, включающими специальный параметр $ IFS
( часть split )
, а затем каждое слово, полученное в результате этого разделения, рассматривается как
шаблон , который расширяется до списка файлов, соответствующих ему
(часть glob ).
Например, если $ var
содержит *. Txt, / var / *. Xml
и $ IFS
содержит ],
, cmd
будет вызываться с рядом аргументов,
первый из них - cmd
, а следующие - txt
файлы в текущем каталоге и файлы xml
в / var
.
Если вы хотите вызвать cmd
только с двумя буквальными аргументами cmd
и *. Txt, / var / *. Xml
, вы бы написали:
cmd "$var"
что было бы на другом вашем более знакомом языке:
cmd($var)
В конце концов, это известно с незапамятных времен время, когда сценарии оболочки не должны использоваться в контекстах, чувствительных к безопасности. Конечно, хорошо, оставить переменную без кавычек - это ошибка, но она не может причинить столько вреда, не так ли?
Что ж, несмотря на то, что кто-нибудь скажет вам эту оболочку { {1}} скрипты никогда не должны использоваться для веб-CGI, или что, к счастью, в настоящее время большинство систем не позволяют использовать сценарии оболочки setuid / setgid, одна вещь, которая поражает оболочкой (удаленно эксплуатируемая ошибка bash { {1}}, который попал в заголовки в сентябре 2014 г.) показал, что оболочки по-прежнему широко используются там, где им, вероятно, не следует: в CGI, в сценариях подключения DHCP-клиента, в командах sudoers, вызывается командой (если не как ) командами setuid ...
Иногда неосознанно. Например, system ('cmd $ PATH_INFO')
в php
/ perl
/ python
скрипт CGI вызывает оболочку для интерпретации этой командной строки (не говоря уже о том, чтобы
упомянуть тот факт, что cmd
сам может быть сценарием оболочки, и его
автор, возможно, никогда не ожидал, что он будет вызван из CGI).
У вас есть уязвимость, когда есть путь для повышения привилегий, то есть когда кто-то (назовем его злоумышленником ) может сделать то, что он не предназначено.
Неизменно это означает злоумышленник , предоставляющий данные, эти данные обрабатываются привилегированным пользователем / процессом, который непреднамеренно делает то, чего не должен делать, в большинстве случаев случаев из-за ошибки.
По сути, проблема возникает, когда ваш ошибочный код обрабатывает данные под контролем злоумышленника .
Теперь не всегда очевидно, откуда могут взяться эти данные , , и часто трудно сказать, сможет ли ваш код когда-либо обрабатывать ненадежные данные.
Что касается переменных. В случае сценария CGI, это совершенно очевидно, данные - это параметры CGI GET / POST и такие вещи, как файлы cookie, путь, хост. .. параметры.
Для сценария setuid (выполняющегося от имени одного пользователя, когда его вызывает другой) это аргументы или переменные среды.
Другой очень распространенный вектор - это имена файлов. Если вы получаете список файлов из каталога,возможно, файлы были помещены туда злоумышленником .
В этом отношении, даже при запросе интерактивной оболочки, вы
можете быть уязвимы (при обработке файлов в / tmp
или ~ / tmp
{{ 1}}, например).
Даже ~ / .bashrc
может быть уязвимым (например, bash
интерпретирует его при вызове через ssh
для запуска ForcedCommand
как в git
серверных развертываний с некоторыми переменными под управлением клиента
).
Теперь сценарий не может быть вызван напрямую для обработки ненадежных данных , но он может быть вызван другой командой, которая это делает. Или ваш неправильный код может быть скопирован в скрипты, которые это делают (вами через 3 года или одним из ваших коллег). Одно место, где это особенно критично , - это ответы на сайтах вопросов и ответов, поскольку вы никогда не узнаете, где могут оказаться копии вашего кода.
Оставление переменной (или подстановки команды) без кавычек - это, безусловно, источник номер один уязвимостей безопасности, связанных с кодом оболочки. Отчасти потому, что эти ошибки часто приводят к уязвимостям , но также потому, что часто встречаются переменные без кавычек.
На самом деле, при поиске уязвимостей в коде оболочки первое, что нужно сделать, - это найти переменные без кавычек. Легко обнаружить, часто хороший кандидат, обычно легко отследить до данных, контролируемых злоумышленником.
Существует бесконечное количество способов, которыми переменная без кавычек может превратить в уязвимость. Я просто приведу здесь несколько общих тенденций.
Большинство людей столкнутся с ошибками, связанными с переменными без кавычек из-за разделенной части (например, часто в файлах есть пробелы в их именах в настоящее время, а пробел находится в значении IFS по умолчанию). Многие люди упускают из виду часть glob . Часть glob по крайней мере так же опасна, как и разделенная часть .
Глобализация, выполняемая при необработанном внешнем вводе, означает злоумышленник может заставить вас прочитать содержимое любого каталога.
В:
echo You entered: $unsanitised_external_input
если $ unsanitised_external_input
содержит / *
, это означает, что
злоумышленник может увидеть содержимое /
. Ничего страшного. Это становится
более интересным с помощью / home / *
, который дает вам список
имен пользователей на машине, / tmp / *
, / home / * /. Forward
для
намеков на другие опасные действия, / etc / rc * / *
для включенных
служб ... Нет необходимости назвать их индивидуально. Значение / *
/ * / * / * / * / * ...
просто перечислит всю файловую систему.
Если зайти слишком далеко в предыдущем случае, мы получили DoS-атаку.
Фактически, любая некотируемая переменная в контексте списка с неанитизированным входом является как минимум уязвимостью DoS.
Даже опытные разработчики сценариев оболочки обычно забывают цитировать такие вещи, как:
#! /bin/sh -
: ${QUERYSTRING=$1}
:
- это команда, не выполняющая никаких действий.Что могло пойти не так?
Это означало присвоить $ 1
$ QUERYSTRING
, если $ QUERYSTRING
не задано. Это быстрый способ сделать сценарий CGI вызываемым из
командной строки.
Этот $ QUERYSTRING
все еще раскрывается, и поскольку он
не цитируется, вызывается оператор split + glob .
Есть несколько глобусов, которые особенно дорого расширять
. / * / * / * / *
достаточно плох, так как он означает перечисление каталогов
до 4 уровней ниже. Помимо активности диска и процессора
, это означает сохранение десятков тысяч путей к файлам
(40 КБ здесь на минимальной серверной ВМ, 10 КБ из которых - каталогов).
Теперь /*/*/*/*/../../../../*/*/*/*
означает 40k x 10k и
/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*
достаточно, чтобы
поставить на колени даже самую мощную машину.
Попробуйте сами (хотя будьте готовы к тому, что ваша машина выйдет из строя или зависнет):
a='/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*' sh -c ': ${a=foo}'
Конечно, если код:
echo $QUERYSTRING > /some/file
Тогда вы можете заполнить диск.
Просто выполните поиск в Google по оболочке cgi или bash cgi или ksh cgi , и вы найдете несколько страниц, на которых показано, как писать CGI в оболочках. Обратите внимание , насколько уязвима половина из тех, которые обрабатывают параметры.
Даже собственный файл Дэвида Корна уязвим (посмотрите на обработку файлов cookie).
Выполнение произвольного кода - наихудший тип уязвимости, поскольку, если злоумышленник может выполнить любую команду, нет ограничений на {{1} } что он может делать.
Обычно к ним приводит разделенная часть . Это разделение приводит к тому, что командам передается несколько аргументов, хотя ожидается только один. Хотя первый из них будет использоваться в ожидаемом контексте,другие будут в другом контексте , поэтому потенциально могут интерпретироваться по-разному. Лучше приведите пример:
awk -v foo=$external_input '$2 == foo'
Здесь целью было присвоить содержимое переменной оболочки
$ external_input
переменной foo
awk
.
Теперь:
$ external_input='x BEGIN{system("uname")}'
$ awk -v foo=$external_input '$2 == foo'
Linux
Второе слово, полученное в результате разделения $ external_input
, не присваивается foo
, но считается awk
код (здесь
выполняет произвольную команду: uname
).
Это особенно проблема для команд, которые могут выполнять другие команды
( awk
, env
, sed
(один GNU), ] perl
, find
...) особенно
с вариантами GNU (которые принимают параметры после аргументов).
Иногда вы не подозреваете, что команды может выполнять
другие, например ksh
, bash
или zsh
[
или printf
) ...
for file in *; do
[ -f $file ] || continue
something-that-would-be-dangerous-if-$file-were-a-directory
done
Если мы создадим каталог с именем x -o yes
, тогда тест
станет положительным, потому что это совершенно другое условное выражение
, которое мы оцениваем .
Хуже того, если мы создадим файл с именем x -aa [0 $ (uname> & 2)] -gt 1
,
по крайней мере со всеми реализациями ksh (включая sh
большинства коммерческих Unix и некоторых BSD), который выполняет uname
, потому что эти оболочки выполняют арифметические вычисления для операторов числового сравнения
команда [
.
$ touch x 'x -a a[0$(uname>&2)] -gt 1'
$ ksh -c 'for f in *; do [ -f $f ]; done'
Linux
То же самое с bash
для имени файла, например x -a -v a [0 $ (uname> & 2)]
.
Конечно, если они не могут добиться произвольного выполнения, злоумышленник может согласиться на меньший ущерб (что может помочь добиться произвольного выполнения). Любая команда, которая может записывать файлы или изменять разрешения, права собственности или иметь какой-либо основной или побочный эффект, может быть использована.
С именами файлов можно делать все, что угодно.
$ touch -- '-R ..'
$ for file in *; do [ -f "$file" ] && chmod +w $file; done
И в итоге вы делаете ..
записываемым (рекурсивно с помощью GNU
chmod
).
Скрипты, выполняющие автоматическую обработку файлов в общедоступных областях, таких как / tmp
, должны быть написаны очень осторожно.
[$ # -gt 1]
Меня это раздражает. Некоторые люди упускают все проблемы, задаваясь вопросом, может ли конкретное расширение быть проблематичным, чтобы решить, могут ли они опустить кавычки.
Это как сказать. Эй, похоже, что $ #
не может подчиняться
оператору split + glob, давайте попросим оболочку разделить + glob его .
Или Эй, давайте напишем неверный код только потому, что
ошибка вряд ли будет обнаружена .
Насколько это маловероятно? Хорошо, $ #
(или $!
, $?
или любая
арифметическая подстановка) может содержать только цифры (или -
для
некоторых), поэтому часть glob отсутствует. Однако для того, чтобы часть split что-то делала
, все, что нам нужно, это чтобы $ IFS
содержал цифры (или -
).
В некоторых оболочках $ IFS
может быть унаследован от среды,
но если среда небезопасна, игра все равно окончена.
Теперь, если вы напишете такую функцию, как:
my_function() {
[ $# -eq 2 ] || return
...
}
Это означает, что поведение вашей функции зависит
от контекста, в котором она вызывается. Или, другими словами, $ IFS
становится одним из его входов. Строго говоря, когда вы
пишете документацию по API для своей функции, она должна быть
примерно такой:
# my_function
# inputs:
# $1: source directory
# $2: destination directory
# $IFS: used to split $#, expected not to contain digits...
И код, вызывающий вашу функцию, должен убедиться, что $ IFS
не 't
не содержат цифр. Все потому, что вам не хотелось набирать
эти два символа двойных кавычек.
Теперь, чтобы ошибка [$ # -eq 2]
стала уязвимостью,
вам нужно каким-то образом, чтобы значение $ IFS
стало под
контролем злоумышленника . Возможно, этого обычно не происходило бы
, если бы злоумышленник не смог воспользоваться другой ошибкой.
Это не редкость. Распространенный случай - когда люди забывают очистить данные перед их использованием в арифметическом выражении . Мы уже видели выше, что он может разрешить выполнение произвольного кода в некоторых оболочках, но во всех из них он позволяет злоумышленнику присвоить любой переменной целочисленное значение. .
Например:
n=$(($1 + 1))
if [ $# -gt 2 ]; then
echo >&2 "Too many arguments"
exit 1
fi
И с $ 1
со значением (IFS = -1234567890)
, эта арифметическая
оценка имеет побочный эффект настроек IFS и следующая команда [
завершается ошибкой, что означает, что проверка на слишком большого количества аргументов
пропущена.
Есть еще один случай, когда кавычки нужны вокруг переменных и других расширений: когда он используется в качестве шаблона.
[[ $a = $b ]] # a `ksh` construct also supported by `bash`
case $a in ($b) ...; esac
не проверяет, совпадают ли $ a
и $ b
(кроме zsh
)но если $ a
соответствует шаблону в $ b
. И вам нужно указать $ b
, если вы хотите сравнивать как строки (то же самое в "$ {a # $ b}"
или "$ {a% $ b}} "
или " $ {a ## * $ b *} "
, где $ b
следует заключить в кавычки, если это не следует рассматривать как образец).
Это означает, что [[$ a = $ b]]
может возвращать истину в тех случаях, когда $ a
отличается от $ b
(для например, когда $ a
равно что-нибудь
и $ b
равно *
) или может возвращать false, когда они идентичны (например, когда оба $ a
и $ b
равны [a]
).
Может ли это привести к уязвимости системы безопасности? Да вроде любой баг. Здесь злоумышленник может изменить логический поток кода вашего скрипта и / или нарушить предположения, которые делает ваш скрипт. Например, с таким кодом:
if [[ $1 = $2 ]]; then
echo >&2 '$1 and $2 cannot be the same or damage will incur'
exit 1
fi
Злоумышленник может обойти проверку, передав '[a]' '[a]'
.
Итак, если ни то сопоставление с образцом, ни оператор split + glob не применимы, в чем опасность оставить переменную без кавычек?
Я должен признать, что пишу:
a=$b
case $a in...
Там, цитирование не вредит, но не обязательно.
Однако одним из побочных эффектов опускания кавычек в этих случаях (например, в ответах на вопросы) является то, что это может послать неверное сообщение новичкам: что можно не заключать переменные в кавычки .
Например, они могут начать думать, что если a = $ b
в порядке, то тоже будет (что не во многих shells в аргументах команды export a = $ b
export
в контексте списка) или . env a = $ b
zsh
? zsh
исправил большинство этих неудобств дизайна. В zsh
(по крайней мере, когда не в режиме эмуляции sh / ksh), если вы хотите разбиение , или подстановку , или сопоставление с образцом , вы должны запросить его явно: $ = var
для разделения и $ ~ var
для glob или для того, чтобы содержимое переменной обрабатывалось как шаблон.
Однако разделение (но не глобализация) все еще выполняется неявно при подстановке команд без кавычек (как в echo $ (cmd)
).
Кроме того, иногда нежелательным побочным эффектом отсутствия кавычек для переменной является удаление пустых . Поведение zsh
аналогично тому, что вы можете достичь в других оболочках, полностью отключив подстановку (с помощью set -f
) и разделение (с помощью IFS = ''
) . Тем не менее, в:
cmd $var
Не будет split + glob , но если $ var
пусто, вместо получения одного пустого аргумента cmd
получит вообще никаких аргументов.
Это может вызвать ошибки (например, очевидный [-n $ var]
).Возможно, это может нарушить ожидания и предположения сценария и вызвать уязвимости, но я не могу сейчас привести не слишком надуманный пример).
Да, обычно вы хотите оставить переменную без кавычек. Но тогда вам нужно убедиться, что вы правильно настроили операторы split и glob , прежде чем использовать их. Если вам нужна только часть split , а не часть glob (что имеет место в большинстве случаев), то вам нужно отключить подстановку ( set -o noglob
/ set -f
) и исправьте $ IFS
. В противном случае вы также вызовете уязвимости (например, пример CGI Дэвида Корна, упомянутый выше).
Короче говоря, оставлять переменную (или подстановку команд или арифметическое раскрытие) без кавычек в оболочках может быть очень опасно действительно, особенно когда сделано в неправильном контексте, и это очень трудно понять, какие это неправильные контексты.
Это одна из причин, почему это считается плохой практикой .
Спасибо, что дочитали до сих пор. Если это пролетит над вашей головой, не волнуйтесь. Нельзя ожидать, что все поймут все последствия написания кода так, как они его пишут. Вот почему у нас есть рекомендаций по передовой практике , поэтому им можно следовать, не обязательно понимая почему.
(и в случае, если это еще не очевидно, избегайте написания кода, чувствительного к безопасности, в оболочках).
И , пожалуйста, укажите свои переменные в ответах на этом сайте!
¹В ksh93
и pdksh
и производных, раскрытие фигурных скобок также выполняется, если подстановка не отключена (в случае версий ksh93
вплоть до ksh93u +, даже если опция braceexpand
отключена).
Я скептически отнесся к ответу Стефана, однако можно злоупотребить $ #
:
$ set `seq 101`
$ IFS=0
$ echo $#
1 1
или $ ?:
$ IFS=0
$ awk 'BEGIN {exit 101}'
$ echo $?
1 1
Это надуманные примеры, но потенциал есть.
[На основе этого ответа cas .]
Но что, если мой сценарий устанавливает для переменной известное значение перед ее использованием? В частности, что, если он устанавливает для переменной одно из двух или более возможных значений (но он всегда устанавливает для нее что-то известное), и ни одно из значений не содержит пробелов или символов глобуса? Разве не безопасно использовать его без кавычек в этом случае ?
А что, если одним из возможных значений является пустая строка, и я в зависимости от «удаления пустой тары»? То есть, если переменная содержит пустую строку, я не хочу получать пустую строку в моей команде; я не хочу ничего получать. Например,
if some_condition then ignorecase="-i" else ignorecase="" fi # Note that the quotes in the above commands are not strictly needed. grep $ignorecase other_grep_args
Я не могу сказать grep "$ ignorecase" other_ grep _args
;
это не сработает, если $ ignorecase
- пустая строка.
Как обсуждалось в другом ответе,
это все равно не удастся, если IFS
содержит -
или i
.
Если вы убедились, что IFS
не содержит никаких символов в вашей переменной
(и вы уверены, что ваша переменная не содержит никаких глобальных символов), {{ 1}}, то это, вероятно, безопасно.
Но есть способ более безопасный
(хотя он несколько уродлив и совершенно не интуитивен):
используйте $ {ignorecase: + "$ ignorecase"}
.
Из спецификации языка команд оболочки POSIX ,
в 2.6.2 Расширение параметров ,
$ { параметр : + [ word ]}
Использовать альтернативное значение. Если
параметр
не установлен или равен нулю, должен быть заменен ноль; в противном случае - раскрытиеслова
(или пустая строка, еслислово
опущено) заменяется.
Хитрость здесь, например,
в том, что мы используем ignorecase
как параметр
и «$ ignorecase»
как слово
.
Итак $ {ignorecase: + "$ ignorecase"}
означает
Если
$ ignorecase
не задан или имеет значение null (т. Е. Пусто), null (т. е. без кавычек ничего ) должен быть заменен; в противном случае должно быть заменено расширение«$ ignorecase»
.
Это приводит нас туда, куда мы хотим пойти: если для переменной задана пустая строка, она будет «удалена» (все это запутанное выражение будет вычислить ничего - даже не пустую строку), , и если переменная имеет непустое значение, мы получим это значение в кавычках.
Но что, если у меня есть переменная, которую я хочу / нужно разбить на слова? (В остальном это похоже на первый случай; мой сценарий установил переменную, , и я уверен, что она не содержит никаких глобальных символов. Но она может содержать пробел (s), и я хочу, чтобы он был разделен на отдельные аргументы на границах пространства.
PS Я все еще хочу удалить пустые места.)Например,
if some_condition then criteria="-type f" else criteria="" fi if some_other_condition then criteria="$criteria -mtime +42" fi find "$start_directory" $criteria other_find_args
Вы можете подумать, что это случай использования
Нет!
Не поддавайтесь искушению даже подумать об использовании здесь eval
. eval
.
Опять же, если вы убедились, что IFS
не содержит
ни одного символа в вашей переменной
(кроме пробелов, которые вы хотите учитывать),
и вы уверены, что ваша переменная не содержит каких-либо глобальных символов,
тогда приведенное выше, вероятно, безопасно.
Но если вы используете bash (или ksh, zsh или yash), есть более безопасный способ: используйте массив:
if some_condition then criteria=(-type f) # You could say `criteria=("-type" "f")`, but it’s really unnecessary. else criteria=() # Do not use any quotes on this command! fi if some_other_condition then criteria+=(-mtime +42) # Note: not `=`, but `+=`, to add (append) to an array. fi find "$start_directory" "${criteria[@]}" other_find_args
From bash (1) ,
На любой элемент массива можно ссылаться , используя
$ { name [ индекс ]}
.… Еслиподстрочный индекс
равен@
или*
, слово расширяется до всех членовname
. Эти индексы различаются только в том случае, если слово заключено в двойные кавычки. Если слово заключено в двойные кавычки,…$ { name [@]}
заменяет каждый элементname
на отдельное слово.
Итак "$ {критерии [@]}"
заменяется (в приведенном выше примере)
нулем, двумя или четырьмя элементами массива критериев
. , каждый процитирован.
В частности, если ни одно из условия s не выполняется,
массив критериев
не имеет содержимого
(как установлено критериев = ()
оператор),
и "$ {критерии [@]}"
не оцениваются как ничего
(не даже неудобная пустая строка).
Это становится особенно интересным и сложным , когда вы имеете дело с несколькими словами, некоторые из которых являются динамическим (пользовательским) вводом, о котором вы не знаете заранее, {{1} } и может содержать пробелы или другие специальные символы. Учтите:
printf "Enter file name to look for: " read fname if [ "$fname" != "" ] then criteria+=(-name "$fname") fi
Обратите внимание, что $ fname
цитируется каждый раз, когда используется.
Это работает, даже если пользователь вводит что-то вроде foo bar
или foo *
;
"$ {критерии [@]}"
оцениваются как -имя "foo bar"
или -имя "foo *"
.
(Помните, что каждый элемент массива заключен в кавычки.)
Массивы работают не во всех оболочках POSIX;
массивы - это ksh / bash / zsh / yash-ism.
Кроме… есть один массив, который поддерживают все оболочки:
список аргументов, он же «$ @»
.
Если вы закончили со списком аргументов, с которым вы были вызваны (например,
вы скопировали все «позиционные параметры» (аргументы) в переменные,
или обработали иным образом их), вы можете использовать список аргументов как массив:
if some_condition then set -- -type f # You could say `set -- "-type" "f"`, but it’s really unnecessary. else set -- fi if some_other_condition then set -- "$@" -mtime +42 fi # Similarly: set -- "$@" -name "$fname" find "$start_directory" "$@" other_find_args
Конструкция "$ @"
(которая исторически появлялась первой)
имеет ту же семантику, что и " $ { name [@]} "
-
расширяет каждый аргумент (т. Е. Каждый элемент списка аргументов)
до отдельного слова, как если бы вы набрал «$ 1» «$ 2» «$ 3»…
.
Выдержка из спецификации языка команд оболочки POSIX , в разделе 2.5.2 Специальные параметры ,
@
Расширяется до позиционных параметров, начиная с от одного, первоначально создает одно поле для каждого установленного позиционного параметра. …, исходные поля должны быть сохранены как отдельные поля,…. Если нет позиционных параметров, расширение
@
должно генерировать нулевые поля, даже если@
находится в пределах двойного цитаты; …
Полный текст несколько загадочен;
ключевым моментом является то, что он указывает
, что "$ @"
будет генерировать нулевые поля
, когда есть не являются позиционными параметрами.
Историческое примечание: когда "$ @"
впервые был представлен
в оболочке Bourne (предшественник bash) в 1979 году,
в нем была ошибка, "$ @"
было заменено одной пустой строкой
, когда не было позиционных параметров;
см. Что означает $ {1 + "$ @" }
означает в сценарии оболочки
и чем он отличается от «$ @»
? ,
Традиционное семейство оболочки Борна ,
Что означает $ {1 + "$ @"}
... и где это необходимо? ,
и "$ @"
против $ {1 + "$ @"}
.
Массивы помогают и в первой ситуации:
if some_condition then ignorecase=(-i) # You could say `ignorecase=("-i")`, but it’s really unnecessary. else ignorecase=() # Do not use any quotes on this command! fi grep "${ignorecase[@]}" other_grep_args
Это должно быть само собой разумеющимся, но для удобства новичков: csh, tcsh и т. д. не являются оболочками Bourne / POSIX. Это совсем другая семья. Лошадь другого цвета. Совершенно другая игра с мячом. Кошка другой породы. Птицы другого пера. И, в частности, другая банка с червями.
Кое-что из того, что было сказано на этой странице, относится к csh; например: рекомендуется заключать в кавычки все переменные , если у вас нет веской причины не делать этого, {{1} } и вы уверены, что знаете, что делаете. Но в csh каждая переменная является массивом - так уж получилось, что почти каждая переменная является массивом только из одного элемента и действует примерно одинаково {{1} } в обычную переменную оболочки в оболочках Bourne / POSIX. И синтаксис ужасно другой (я имею в виду ужасно ). Поэтому мы не будем здесь больше ничего говорить об оболочках семейства csh.