Есть ли способ получить * фактические * (неинтерпретированные) аргументы оболочки в функции или скрипте?
У меня есть функция posix
которую я использую в оболочке Git bash в Windows, чтобы преобразовать пути в стиле DOS в обычные пути в стиле Unix. Поскольку пути DOS-типа используют обратную косую черту как разделитель, я должен указать аргумент пути, чтобы предотвратить обратную косую черту как используемую оболочкой, чтобы обозначить следующий символ как литерал. Есть ли способ получить неинтерпретированный аргумент внутри моей функции, так что мне не нужно указывать его?
Вот моя функция, если это помогает:
- Проблема использования пользовательской переменной в скрипте
- Почему команда grep игнорирует период в строке поиска?
- Новая строка в переменных bash
- Почему в моем выражении grep нужно использовать $ 'string' для соответствия символам табуляции?
- Передача аргументов с кавычками и двойными значениями в сценарий bash
function posix() { echo $1 | sed -e 's|\\|/|g' | sed -re 's|^(.)\:|/\L\1|' }
(Кстати, я приветствую любые комментарии с советами по улучшению функции другими способами, не связанными с решением проблемы цитирования / интерпретации оболочки).
- sed - не добавляет новую строку EOF и заменяет букву не определенной
- Параметр игнорируется при цитировании
- Почему двойные кавычки и backquotes в сценарии оболочки?
- cp не работает в скрипте, но работает в терминале
- Ошибка с именем файла, содержащим круглые скобки
- Регулярное выражение с использованием \\ vs с использованием \
- Плохая замена внутри подошвы xargs?
- Измените каталог с пробелом, за которым следует '('
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 на этом очень хорошая. Вкратце, такие вещи, как расширение тильды, происходят очень рано (и расширение тильды только в определенных ситуациях). Затем происходит переменная подстановка и расщепление слов и, наконец, глотание.
- Удалите пробелы, кроме строк, начинающихся с определенного шаблона
- Работает ли работа cron как таковая на современном уровне?