Существует ли способ стать *фактическим* (неинтерпретируемые) аргументы оболочки в функции или сценарии?

Команда tee точно делает это:

cat /dev/stdin | tee $logfile
3
29.09.2012, 03:06
3 ответа

Неинтерпретируемые аргументы оболочки $1, $2, и т.д. Необходимо поместить их расширение в двойные кавычки в большинстве контекстов, для предотвращения значения параметра, расширяемого далее. "$@" дает Вам список всех параметров.

Например, если Вы хотите передать аргумент сценария оболочки к Вашей функции, назовите его как это:

first_argument_as_filename_in_unix_syntax=$(posix "$1")

Двойные кавычки необходимы. Если Вы пишете posix $1, затем то, что Вы являетесь передающими, не является значением первого параметра, но результатом работающего разделения слова и globbing на значении первого параметра. Необходимо будет использовать надлежащее заключение в кавычки при вызове сценария, также. Например, если Вы пишете это в ударе:

myscript c:\path with spaces\somefile

затем фактические, неинтерпретируемые аргументы myscript будет c:path, with и spacessomefile. Не делайте этого.

Ваш posix функция является неправильной, снова потому что она испытывает недостаток в двойных кавычках вокруг $1. Всегда помещайте двойные кавычки вокруг переменной и управляйте заменами: "$foo", "$(foo)". Легче помнить это правило, чем исключения, где Вам на самом деле не нужны кавычки.

echo делает его собственную обработку в некоторых случаях, и вызов внешних процессов является медленным (особенно в Windows). Можно сделать целую обработку в ударе.

posix () {
  path="${1//\\//}"
  case "$path" in
    ?:*) drive="${p:0:1}"; drive="${drive,}"; p="/$drive/${p:2}";;
  esac
  printf %s "$p"
}

zsh функция, на которую сослался jw013, не делает то, что Вы, кажется, думаете, что это делает. Можно поместить noglob перед командой и zsh не выполняет globbing (т.е. поколение имени файла, т.е. расширение подстановочных знаков) на аргументах. Например, в zsh, если Вы пишете noglob locate *foo*bar*, затем locate назван с аргументом *foo*bar*. Вы обычно скрывались бы noglob встроенный позади псевдонима. Эта функция не важна, для какого Вы пытаетесь сделать.

6
27.01.2020, 21:09
  • 1
    Спасибо за чрезвычайно полный ответ и большие улучшения к функции. Это кажется, что мое использование "неинтерпретируемых" не было четким, как бы то ни было. Под чем я подразумеваю, который является фактическими символами, я ввел на командной строке (включая''), но после разделения вещей в отдельные аргументы. Если я читаю между строк этих ответов правильно, проблема может состоять в том, что разделение на отдельные аргументы происходит после расширения и обработки заключения в кавычки и т.д, и оболочка не предлагает способа изменить этот факт. Это корректно? –  iconoclast 29.09.2012, 06:27
  • 2
    @iconoclast заключения в кавычки происходит вначале в расширении, оболочка должна знать, например, это echo 'foo; bar' имеет точку с запятой в аргументе echo и не как разделитель команды. Расширение значений переменных происходит позже, и разделяющий на слова еще позже. “Фактические символы, которые Вы ввели на командной строке”, только значимы в оболочке, где Вы ввели их; при использовании оболочки с различными правилами заключения в кавычки или никакой оболочки вообще они имели бы другое значение, или не будет такой вещи. –  Gilles 'SO- stop being evil' 29.09.2012, 15:42

У Вас не может быть процесса оболочки "неинтерпретируемый" вход. То, что Вы вводите в командной строке, является просто строкой символов, точно намеревался быть интерпретированным оболочкой. У Вас не может быть передачи оболочки Ваш литерал, введенный, символы к функции или команде, потому что это должно интерпретировать их для знания что команду/функцию вызвать и с какой аргументы! При вводе чего-то в командной строке необходимо признать, что необходимо ввести согласно правилам интерпретации оболочки (потому что Вы используете оболочку!).

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

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

2
27.01.2020, 21:09

В то время как другие ответы могут быть корректными в заявлении, что Вы не можете получить "неинтерпретируемый" вход оболочки через средства, которые они упоминают, они неправы в категориальном отклонении его как возможность. Можно, конечно, получить его, прежде чем оболочка интерпретирует его, если Вы даете оболочке команду не интерпретировать его. Скромный POSIX heredoc делает это очень просто возможным:

% sed -e 's@\\@/@g' -e 's@\(.\):\(.*\)@/drive/\1\2@' <<'_EOF_'     
> c:\some\stupid\windows\place
> _EOF_
/drive/c/some/stupid/windows/place

EDIT1:

Для передачи такой строки функции оболочки как аргумент оболочки, Вы испытываете необходимость для хранения ее в переменной оболочки. Обычно Вы не можете просто var=<<'HEREDOC' к сожалению, но POSIX действительно указывает -r аргумент read встроенный:

% man read

РУКОВОДСТВО ПРОГРАММИСТА POSIX

...

По умолчанию, если-r опция не указана, обратная косая черта ('\') должна действовать как символ ESC, как описано в Символе ESC (Обратная косая черта). Если стандартный вход будет оконечным устройством, и оболочка вызова является интерактивной, читайте, то запрошу строку продолжения когда:

  • Оболочка читает входную строку, заканчивающуюся обратной косой чертой, если-r опция не указана.

  • Здесь-документ не завершается после того, как новая строка вводится.

При объединении, read и heredoc сделайте это тривиальным и портативным вопросом также, хотя это не может чувствовать себя очень интуитивным сначала:

% _stupid_mspath_fix() { 
> sed -e 's@\\@/@g' -e 's@\(.\):\(.*\)@/drive/\1\2@' <<_EOF_
>> ${1}
>> _EOF_
> }
% read -r _stupid_mspath_arg <<'_EOF_'                    
> c:\some\stupid\windows\place
> _EOF_
% _stupid_mspath_fix ${_stupid_mspath_arg}
/drive/c/some/stupid/windows/place

EDIT2:

Вероятно, Вы заметили различие между двумя heredocs во втором примере. heredoc _EOF_ разделитель в функции закрывается кавычки, в то время как та, питаемая к read заключается в кавычки с одинарными кавычками. Таким образом оболочка проинструктирована для выполнения расширения на heredoc с неупомянутым разделителем, но не сделать так, когда его разделитель заключается в кавычки. Это не повреждается при расширении неупомянутого heredoc в функции, потому что значение переменной это расширяется, уже установлен как заключенная в кавычки строка, и это не анализирует его дважды.

Вероятно, то, что Вы хотите сделать, включает передачу по каналу Вашего пути Windows от вывода одной команды во вход другого динамично. Замена команды в a heredoc делает это возможным:

% _stupid_mspath_fix() { 
> sed -e 's@\\@/@g' -e 's@\(.\):\(.*\)@/drive/\1\2@' <<_EOF_
>> ${1}
>> _EOF_
> }
% read -r _stupid_mspath_arg <<'_EOF_'                    
> c:\some\stupid\windows\place
> _EOF_
% _stupid_mspath_fix ${_stupid_mspath_arg}
/drive/c/some/stupid/windows/place    
% read -r _second_stupid_mspath_arg <<_EOF_                    
> $(printf ${_stupid_mspath_arg})
> _EOF_
% _stupid_mspath_fix ${_second_stupid_mspath_arg}
/drive/c/some/stupid/windows/place

Так в основном, если можно надежно произвести обратные косые черты из некоторого приложения (я использовал printf выше), затем выполняя ту команду в $(...) и включение этого в неупомянутом heredoc переданный другому приложению, которое может надежно принять обратные косые черты как вход (такой как read и sed выше), обойдет парсинг оболочки Ваших обратных косых черт в целом. Могут ли приложения обработать обратные косые черты, поскольку ввод/вывод - что-то, что необходимо будет узнать для себя.

Не строго относящийся к вопросу:

В ответе Gilles он рекомендует ${var/search/replace} форма расширения параметра, которая, хотя прохладный, не является POSIX. Это - определенно bashism. Это не имело бы значения для меня, но в его редактированиях он сохранил posix () имя функции, и это может вводить в заблуждение некоторым.

На той ноте, исходное сообщение posix () функция использует очень удобный расширенный regex sed -r аргумент, но это также, к сожалению, не POSIX. POSIX не указывает расширенный regex аргумент в пользу sed, и его использование поэтому возможно ненадежно.

Моя учетная запись при переполнении стека - только несколько только дни также, но я отправил несколько ответов, там имеющих дело конкретно с расширением параметра POSIX, с которым можно найти связанным от моей страницы профиля, и в который я включаю кавычки из инструкций POSIX и ссылок к тому. Вы также найдете некоторых, в которых я демонстрирую другое использование heredoc, такой как чтение всего сценария оболочки в переменную оболочки, парсинг и управление им программно, затем наконец выполняя его новую версию все сделанные из другого сценария или функции оболочки. Просто высказывание.

4
27.01.2020, 21:09
  • 1
    Удивительный ответ! Это могло бы взять меня некоторое время для поглощения всего этого. –  iconoclast 26.11.2013, 04:08
  • 2
    я пытаюсь сделать то же - вот почему, я записал это. Я полагаю, что время, что я изучил, как написать сценарий, таким образом, я медленно прокладываю себе путь посредством записи ответов на вопросы, я нахожу интересными в надеждах, что я изучу что-то в это время. –  mikeserv 26.11.2013, 06:32

Теги

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