Я видел пару похожих тем, но они не ссылаются на переменные, которые, как я знаю, могут привести к нежелательным результатам.
Я видел этот код, и мне было интересно узнать, можно ли внедрить что-то для запуска при выполнении этой строки кода:
echo run after_bundle
Ответы:
Для конкретного случая
цитирование не нужно. Заключение в кавычки не требуется, поскольку аргументом
echo
являются статические строки, которые не содержат раскрытия переменных или подстановок команд и т. Д. Они являются «просто двумя словами» (и, как указывает Стефан , они дополнительно создаются из переносимого набора символов ).«Опасность» возникает, когда вы имеете дело с переменными данными, которые оболочка может расширять или интерпретировать. В таких случаях необходимо позаботиться о том, чтобы оболочка сделала правильные вещи и чтобы результат был именно тем, что предполагалось.
Следующие два вопроса содержат соответствующую информацию об этом:
echo
иногда используется для «защиты» потенциально опасных команд в ответах на этом сайте. Например, я могу показать, как удалить файлы или переместить файлы в новое место назначения, используяили
Это выведет команды на терминал вместо того, чтобы фактически удалять или переименовывать файлы. Затем пользователь может проверить команды, решить, что они выглядят нормально, удалить
echo
и снова запустить.Ваша команда
echo run after_bundle
может быть инструкцией для пользователя или «закомментированным» фрагментом кода, который слишком опасен для выполнения, не зная последствий.Используя ,
echo
как это, один должен знать , что модифицированная команда делает , и один должен гарантировать , что измененная команда на самом деле является безопасным (она потенциально не будет , если в нем содержится переназначения, и использовать его на трубопроводе не работает, и т.д.)источник
echo rm "first file.txt" "second file.txt"
это каким-либо образом отличается от тогоecho rm "first" "file.txt" "second" "file.txt"
, что результат обоих одинаков. Если вы хотите сгенерировать команду оболочки в качестве вывода, нужно использоватьprintf '%q ' rm "first file.txt" "second file.txt"; echo
или что-то эквивалентное, которое повторно генерирует синтаксические кавычки, которые оцениваютargv
переданные.sh
не являются чем-то необычным, и люди видят вопрос: «Почемуfoo
работает, когда я запускаю его в командной строке, а этот сценарий, который выдает эту точную строкуecho
перед строкой, нет? " происходит все время здесь. Более того, вывод отладочной информации бесполезен, если он скрывает ваши ошибки - и если ваши ошибки связаны с цитированием, тоecho
не будут их обнаруживать.Просто дополнительная заметка поверх прекрасного ответа @ Kusalananda .
это хорошо, потому что ни один из символов в этих трех аргументах не передается, чтобы
echo
содержать символы, которые являются специальными для оболочки.И (дополнительный момент, который я хотел бы здесь отметить), нет системного языкового стандарта, где эти байты могли бы преобразовываться в символы, которые являются специальными для оболочки.
Все эти символы находятся в том, что POSIX называет переносимым набором символов . Эти символы должны присутствовать и кодироваться одинаково во всех наборах символов в системе POSIX².
Так что командная строка будет интерпретироваться одинаково независимо от локали.
Теперь, если мы начнем использовать символы вне этого переносимого набора символов, будет хорошей идеей заключить их в кавычки, даже если они не являются специальными для оболочки, потому что в другой локали байты, которые их составляют, могут интерпретироваться как разные символы, которые могут стать специально для оболочки. Обратите внимание, что
echo
проблема заключается в том, используете ли вы какую-либо другую команду или нет, а не вecho
том, как оболочка анализирует свой код.Например, в UTF-8:
Это
à
кодируется как 0xc3 0xa0. Теперь, если у вас есть эта строка кода в сценарии оболочки, и сценарий оболочки вызывается пользователем, который использует локаль, чья кодировка не UTF-8, эти два байта могут составлять совершенно разные символы.Например, в
fr_FR.ISO8859-15
локали, типичной французской локали, использующей стандартную однобайтовую кодировку, которая охватывает французский язык (то же самое, что используется для большинства западноевропейских языков, включая английский), этот байт 0xc3 интерпретируется какÃ
символ, а 0xa0 как не символ пробела.И в некоторых системах, таких как NetBSD³, этот неразрывный пробел считается пустым символом (
isblank()
в нем он возвращает true, ему соответствует[[:blank:]]
), и оболочки вроде быbash
поэтому рассматривают его как разделитель токенов в своем синтаксисе.Это означает, что вместо запуска
echo
с$'voil\xc3\xa0'
аргументом as они запускают его с$'voil\xc3'
аргументом as, что означает, что он не будет печататьсяvoilà
правильно.Это становится намного хуже китайскими наборами символов , такими как BIG5, BIG5-HKSCS, GB18030, ГКИ , которые имеют много символов , чьих кодирования содержит ту же кодировку, что
|
,`
,\
(назвать наихудшее) (также , что нелепое SJIS, иначе Microsoft кандзи, за исключением что это¥
вместо\
, но все еще рассматривается как\
большинство инструментов, поскольку это закодировано как 0x5c).Например, если в
zh_CN.gb18030
китайском языковом стандарте вы пишете скрипт:Этот сценарий будет выводиться
詜 reboot
в локали, использующей GB18030 или GBK,唰 reboot
в локали, использующей BIG5 или BIG5-HKSCS, но в локали C, использующей ASCII, или локали, использующей ISO8859-15 или UTF-8, будетreboot
выполняться из-за кодировки GB18030 из詜
0xd4 0x7c и 0x7c является кодировкой|
в ASCII, поэтому мы в конечном итоге запустим:(что, однако, представляет байт 0xd4, отображается в локали). Пример использования менее вредных
uname
вместоreboot
:(
uname
был запущен).Поэтому я бы посоветовал заключить в кавычки все строки, которые содержат символы вне переносимого набора символов.
Однако обратите внимание, что поскольку кодировка
\
и`
встречается в кодировке некоторых из этих символов, лучше не использовать\
или"..."
или$'...'
(внутри которых`
и / или\
все еще являются специальными), а'...'
вместо этого заключать символы в кавычки вне переносимого набора символов.Я не знаю ни одной системы, в которой есть языковой стандарт, в котором кодировка содержит какой-либо символ (кроме
'
самого себя), кодировка которого содержит кодировку'
, так что она'...'
определенно должна быть самой безопасной.Обратите внимание, что несколько оболочек также поддерживают
$'\uXXXX'
нотацию для выражения символов на основе их кодовой точки Unicode. В таких оболочках, какzsh
иbash
, символ вставляется закодированным в кодировку локали (хотя это может вызвать неожиданное поведение, если эта кодировка не содержит этот символ). Это позволяет вам избегать вставки не-ASCII символов в ваш код оболочки.Итак, выше:
Или:
(с оговоркой, он может сломать скрипт при запуске в локалях, которые не имеют этих символов).
Или лучше, так как
\
это также специально дляecho
(или, по крайней мере, для некоторыхecho
реализаций, по крайней мере, для Unix-совместимых):(обратите внимание, что
\
это также особенное в первом аргументе дляprintf
, поэтому лучше не использовать символы, не входящие в ASCII, в случае, если они могут содержать кодировку\
).Обратите внимание, что вы также можете сделать:
(это было бы излишним, но могло бы дать вам некоторое спокойствие, если вы не уверены, какие символы входят в переносимый набор символов)
Также убедитесь, что никогда не используете древнюю
`...`
форму подстановки команд (которая вводит другой уровень обработки обратной косой черты), но используйте$(...)
вместо этого.¹ технически,
echo
также передаются в качестве аргумента вecho
полезность (чтобы сказать ему , как он был запущен), этоargv[0]
иargc
есть 3, хотя в большинстве оболочек в настоящее времяecho
является встроенным, так чтоexec()
из/bin/echo
файла со списком 3 аргументов моделируются оболочка. Также принято считать, что список аргументов начинается со второго (argv[1]
toargv[argc - 1]
), поскольку это те команды, на которые в основном воздействуют команды.² заметное исключение из того, что это нелепая
ja_JP.SJIS
локаль систем FreeBSD, чья кодировка не имеет\
ни~
символа!³ обратите внимание, что хотя многие системы (FreeBSD, Solaris, но не GNU) рассматривают U + 00A0 как a
[[:blank:]]
в локалях UTF-8, немногие делают это в других локалях, таких как ISO8859-15, возможно, чтобы избежать такого рода проблем.источник
echo
...», я считаю только 2 аргумента, передаваемых командеecho
, аргументы, которые я могу сосчитать,run
иafter_bundle
, как объяснить, как вы посчитал и получил 3 аргумента?echo
). См. В(exec -a foo /bin/echo --help)
системе GNU и с оболочкой GNU, как передать произвольный первый аргумент/bin/echo
утилите.$0
и позиционные параметры в оболочках.iconv
в которыеESC
преобразуется в'
. Попробуйте (в качестве примера):printf '\x1b'|iconv -f utf8 -t IBM-937|xxd
'
. Попробуйprintf '\u2804' | iconv -f utf8 -t BRF | xxd
. Есть кодировки, в которых есть много кодовых точек, которые становятся'
. Около 8695 кодовых точек в UCS-4 становятся'
. Попробуйprintf '\U627' | iconv -cf utf-8 -t UCS-4
. Несколько (37) кодировок преобразуют символ 0x127 в a'
. Попробуйтеprintf '\U127' | iconv -cf utf8 -t UCS2 |xxd