2015-10-08 14 views
3

Got любопытным удивлены:Неожиданные строк избежать в процессе ARGV

$ node -p 'process.argv' $SHELL '$SHELL' \t '\t' '\\t' 
[ 'node', '/bin/bash', '$SHELL', 't', '\\t', '\\\\t' ] 

$ python -c 'import sys; print sys.argv' $SHELL '$SHELL' \t '\t' '\\t' 
['-c', '/bin/bash', '$SHELL', 't', '\\t', '\\\\t'] 

Ожидаемый такое же поведение, как и с:.

$ echo $SHELL '$SHELL' \t '\t' '\\t' 
/bin/bash $SHELL t \t \\t 

который, как мне нужен материал, чтобы быть передан в

Почему дополнительный побег с '\t', '\\t' в процессе argv? Почему обрабатывается иначе, чем '$SHELL'? Откуда это происходит? Почему отличается от поведения echo?

Сначала я подумал, что это будет дополнит. на части minimist, но затем получил то же самое с обоими голой Node.js и Python. Здесь может быть что-то очевидное.

+0

Я предполагаю, что вы пропустили это разница между тем, что содержит строку, и как строка вводится в программу. Например, что вы ожидаете от значений python-выражений 'len (" \ n ")' и 'len (" \\ n ")'? А что такое python/node.js, показывающий вам, когда вы печатаете список/массив? Я добавил гораздо более длинный ответ. – rici

ответ

2

Используйте $'...' форму, чтобы передать управляющие последовательности, как \t, \n, \r, \0 и т.д. в BASH:

python -c 'import sys; print sys.argv' $SHELL '$SHELL' \t $'\t' $'\\t' 
['-c', '/bin/bash', '$SHELL', 't', '\t', '\\t'] 

В соответствии с man bash:

Слова форме $'string' обрабатывают специальным образом. Слово расширяется до строки с заменой символов с обратным слэшем, как указано в стандарте ANSI C. Управляющие последовательности с обратной косой чертой, если они присутствуют, декодируются следующим образом:

\a  alert (bell) 
\b  backspace 
\e 
\E  an escape character 
\f  form feed 
\n  new line 
\r  carriage return 
\t  horizontal tab 
\v  vertical tab 
\\  backslash 
\'  single quote 
\"  double quote 
\nnn the eight-bit character whose value is the octal value nnn (one to three digits) 
\xHH the eight-bit character whose value is the hexadecimal value HH (one or two hex digits) 
\uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits) 
\UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits) 
\cx a control-x character 
+0

Спасибо, хорошо работает. Позаботьтесь о том, почему так и почему это отличается от 'echo'? Я пытаюсь отделить некоторые общие правила от этого. Если нет, я думаю, что это так :) – famousgarkin

+0

Собственно, 'echo' также нуждается в этом. В вашей оболочке введите 'echo 'foo \ tbar'', а затем введите' echo $' foo \ tbar''. Сначала будет выведено 'foo \ tbar', а 2nd будет' foo \t bar', где '\ t' будет интерпретироваться правильно. В ответе я добавил соответствующий раздел 'man bash'. – anubhava

1

В обоих питона и Node.js, есть разница между тем, как print работает со скалярными строками и, как она работает с коллекциями.

Строки печатаются просто как последовательность символов. Получаемый результат обычно является тем, что ожидает пользователь, но он не может использоваться как представление строки на языке. Но когда распечатывается список/массив, то, что вы получаете, является допустимым литералом list/array, который может использоваться в программе.

Например, в Python:

>>> print("x") 
x 
>>> print(["x"]) 
['x'] 

При печати строки, вы видите только символы. Но при печати списка, содержащего строку, python добавляет символы кавычек, так что вывод является допустимым литералом списка. Кроме того, было бы добавить обратную косую черту, если это необходимо:

>>> print("\\") 
\ 
>>> print(["\\"]) 
['\\'] 

Node.js работает точно таким же образом:

$ node -p '"\\"' 
\ 
$ node -p '["\\"]' 
[ '\\' ] 

При печати строку, содержащую один символ обратной косой черты, вы просто получите один обратный слэш , Но когда вы печатаете список/массив, содержащий строку, состоящую из одной обратной косой черты, вы получаете строку с кавычками, в которой обратная косая черта сбрасывается с помощью обратного слэша, что позволяет использовать ее как литерал в программе.

Как и при печати строк в узле и python, стандартная утилита оболочки echo просто печатает фактические символы в строке. В стандартной оболочке нет механизма, сходного с печатанием массивов на узлах и питонах.Bash, однако, обеспечивает механизм для распечатки значения переменного в формате, который может быть использован в качестве части программы Баша:

$ quote=\" 
# $quote is a single character: 
$ echo "${#quote}" 
1 
# $quote prints out as a single quote, as you would expect 
$ echo "$quote" 
" 
# If you needed a representation, use the 'declare' builtin: 
$ declare -p quote 
declare -- quote="\"" 
# You can also use the "%q" printf format (a bash extension) 
$ printf "%q\n" "$quote" 
\" 

(Список литературы:. Баш руководства по declare и printf Или типу help declare и help printf в Баш сессии.)


Это не полная история, хотя. Также важно понять, как оболочка интерпретирует то, что вы набираете. Другими словами, когда вы пишете

some_utility \" "\"" '\"' 

Что some_utility фактически видеть в массиве ARGV?

В большинстве контекстов стандартной оболочки (включая bash) последовательности escape-последовательностей C-типа, такие как \t, не интерпретируются как таковые. (Стандартная утилита оболочки printf интерпретирует эти последовательности, когда они появляются в строке формата, а некоторые другие стандартные утилиты также интерпретируют последовательности, но сама оболочка не делает этого.) Обработка обратной косой черты стандартной оболочкой зависит от контекста:

  • Некотируемые строки: обратный слеш цитирует следующий символ, то, что это (если он не является новой строки, в этом случае как обратная косая черта и символ новой строки удаляются от входа).

  • строк в двойных кавычках: обратный слэш может быть использован, чтобы избежать символов $, \, ", `, также обратный слэш с последующим переводом строки удаляется из входа, как и в некорректная строка. В bash, если расширение истории включено (по умолчанию оно находится в интерактивных оболочках), обратная косая черта также может использоваться для предотвращения расширения истории !, но обратная косая черта сохраняется в последней строке.

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

Bash добавляет еще два цитирования механизма:

  • C-стиль квотирования, $'...'. Если одноколейной строке предшествует знак доллара, то escape-последовательности C-стиля внутри строки равны, которые интерпретируются примерно так же, как компилятор C. Это включает в себя стандартные пробельные символы, такие как символ новой строка (\n), восьмеричные, шестнадцатеричные и Юникод побеги (\010, \x0a, \u000A, \U0000000A), плюс несколько последовательностей не-C, включая «контрольный» символы (\cJ) и символ ESC \e или \E (то же, что и \x1b). Обратные слэши также могут использоваться для выхода \, ' и ".(Обратите внимание, что это другой список из списка сглаживаемых символов в строках с двойными кавычками, здесь обратная косая черта перед знаком доллара или обратной сеткой равна , а не, тогда как обратная косая черта перед отдельной цитатой является специальной, более того, обратная косая черта-последовательность строк не интерпретируется.)

  • Местный-специфический перевод: $"...". Если для строки с двойными кавычками предшествует знак доллара, обратные слэши (и переменные расширения и подстановки команд) интерпретируются как нормальные строки с двойными кавычками, а затем строка просматривается в каталоге сообщений, определяемом текущей локалью.

(Литература. Posix standard, Bash manual)