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

У меня есть функция posix которую я использую в оболочке Git bash в Windows, чтобы преобразовать пути в стиле DOS в обычные пути в стиле Unix. Поскольку пути DOS-типа используют обратную косую черту как разделитель, я должен указать аргумент пути, чтобы предотвратить обратную косую черту как используемую оболочкой, чтобы обозначить следующий символ как литерал. Есть ли способ получить неинтерпретированный аргумент внутри моей функции, так что мне не нужно указывать его?

Вот моя функция, если это помогает:

 function posix() { echo $1 | sed -e 's|\\|/|g' | sed -re 's|^(.)\:|/\L\1|' } 

(Кстати, я приветствую любые комментарии с советами по улучшению функции другими способами, не связанными с решением проблемы цитирования / интерпретации оболочки).

3 Solutions collect form web for “Есть ли способ получить * фактические * (неинтерпретированные) аргументы оболочки в функции или скрипте?”

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

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

 first_argument_as_filename_in_unix_syntax=$(posix "$1") 

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

 myscript c:\path with spaces\somefile 

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

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

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

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

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

В то время как другие ответы могут быть правильными, заявляя, что вы не можете получать «неинтерпретированный» ввод оболочки через средства, которые они упоминают, они ошибочны, категорически отрицая это как возможность. Вы можете, конечно, получить его, прежде чем оболочка интерпретирует его, если вы поручите оболочке не интерпретировать его. Смиренный 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' сожалению, вы не можете просто var=<<'HEREDOC' , но POSIX задает аргумент -r для read builtin:

 % man read 

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

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

  • Оболочка считывает строку ввода, заканчивающуюся обратным слэшем, если не указана опция -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 во втором примере. _EOF_ heredoc _EOF_ внутри функции не кавыдается, а тот, который подается на read , цитируется одинарными кавычками. Таким образом, оболочке дается указание выполнить расширение на heredoc с некотируемым терминатором, но не делать этого, когда его терминатор цитируется. Он не прерывается при расширении некотируемого heredoc в функции, потому что значение переменной, которую он расширяет, уже задано как строка с кавычками и не анализирует его дважды.

Вероятно, то, что вы хотите сделать, связано с тем, что динамический путь вашей очереди Windows выводит одну команду на вход другой. Замена команды в 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 выше) обойдутся разборкой оболочки вашей обратной косой черты. Независимо от того, смогут ли приложения обрабатывать обратную косую черту, поскольку ввод / вывод – это то, что вам нужно будет выяснить самостоятельно.

Не имеет особого значения для вопроса:

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

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

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

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

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

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

  • Одинарная кавычка в двойных кавычках и справочное руководство Bash
  • Двойные кавычки в bash
  • Escaping * с регулярными выражениями и Grep
  • Какие символы мне нужно избегать при использовании sed в сценарии sh?
  • Сценарии - Папки с пробелами
  • Есть ли причина, чтобы указать статус выхода $? переменная?
  • Почему эти вложенные параметры в сценарии оболочки POSIX разделены словом?
  • Многострочная переменная с пробелами, добавление каждой строки в массив
  • Использование ссылки на строковую переменную bash в sed
  • Почему исходный текст не работает, когда я вызываю bash -c
  • Новая строка в переменных bash
  • Interesting Posts

    grep-шаблоны из файла1 в столбец file2

    Является ли ссылка symlink относительно родительского каталога адресата, и если да, то почему?

    Windows Server 2012 R2 и Centos 7 с двойной загрузкой: Windows ушла из меню загрузки

    Как переключить tty со сценарием / cronjob

    Поиск в обратном и прямом направлениях осуществляется с помощью vi-режима в zsh

    Режим монитора wifi только для просмотра широковещательных пакетов

    Самый безопасный способ удалить USB-накопитель на Linux

    Исходный плагин Audio CD для .wav-файлов. Linux

    Аутентификация и авторизация D-Bus

    Изменение строк в файле только в том случае, если они соответствуют шаблонам в другом файле

    Проверка резервной копии .tar.gz

    Различия и преимущества оконных менеджеров в xcb (libxcb) над ними в libx11?

    RT3592BC8 Bluetooth и FreeBSD

    Копирование файлов с одного сервера на другой сервер без запроса пароля

    Как обновить только важные пакеты безопасности в redhat 5.6

    Linux и Unix - лучшая ОС в мире.