#parameters #parameter-passing #options #fish
#параметры #параметр-передача #fish
Вопрос:
У меня есть ряд случаев, когда мне нужно передавать строки произвольной формы (т. Е. Содержащие пробелы и символы, а также алфавитные символы) в качестве параметров функции в fish shell.
Вот пример, в котором я пытаюсь использовать getopts (безрезультатно):
function create_a_note --description 'create a new text note'
set -l title ''
set -l tags ''
getopts $argv | while read -l key value
switch $key
case t title
set title $value
case g tags
set tags $value
end
end
if test -z $title
error "title must be set (use the -t option)" >amp;2
return 1
end
# do something interesting with the title and tags
end
Я вызываю это следующим образом:
create_a_note -t 'my very interesting note' -g '@blah @rhubarb'
Всякий раз, когда я использую такой подход, переменные $title
и $tags
получают первое слово строк (т. Е. $title == 'my'
и $tags == '@blah'
), а не всю строку. Я понимаю, почему это происходит, когда строка преобразуется в список и возвращается первый элемент списка.
Мой вопрос — есть ли способ обойти это в fish shell? Я не хочу просто передавать $argv
и анализировать это самостоятельно, если нет другого варианта.
Использование getopts
необязательно, если вы простите за каламбур.
Комментарии:
1. использование
fish, version 3.0.2
в NixOS2. Вы могли бы изучить
argparse
команду вместо использования getopts.
Ответ №1:
Я предлагаю прекратить использовать getopts
интерфейс, который я никогда не могу получить правильно, и вместо этого использовать встроенный инструмент анализа аргументов fish, argparse
.
function create_a_note --description 'create a new text note'
set -l title ''
set -l tags ''
argparse 't/= ' 'g/= ' -- $argv
if test -z "$_flag_t"
echo "title must be set (use the -t option)" >amp;2
return 1
end
echo $_flag_t; echo $_flag_g
end
В частности, argparse 't/= ' 'g/= '
означает « -t
параметр, для которого требуется аргумент, и -g
параметр, для которого требуется аргумент». Эти аргументы хранятся в $_flag_t
и $_flag_g
соответственно. Больше информации в руководстве argparse.
Комментарии:
1. Это тоже не сработало, что заставило меня копать глубже. На самом деле я вызываю эту функцию с помощью своего рода механизма косвенного обращения, который завершается вызовом, подобным этому:
eval "$$fun $params"
. Я думаю, проблема в том, что интерполяция / встраивание строк удаляет символы кавычек. Когда я вызываю функцию напрямую, ваше решение работает нормально (я не удивлюсь, если getopts тоже работает нормально!). Отметьте свой ответ как решение. Спасибо.
Ответ №2:
Я думаю, вам нужно будет использовать двойные кавычки: $example == "example text w/ spaces and quotes"
. Или вам может потребоваться избежать пробелов: $example == 'example text w/ spaces and backslashes'
. Кроме того, если использовать Википедию, каждая переменная является массивом, поэтому вам может потребоваться получить содержимое массива вместо первого значения в массиве, что, я думаю, и происходит.
РЕДАКТИРОВАТЬ: я неправильно прочитал вопрос. В любом случае решение было бы почти таким же:
- Кавычки:
create_a_note -t "my very interesting note" -g "@blah @rhubarb"
- Побег»
create_a_note -t my very interesting note -g @blah @rhubarb
Комментарии:
1. Я пробовал различные формы цитирования — не работает. Что касается экранирования всего — это недостаточно удобно для пользователя, чтобы быть полезным. Я пропускаю строку заголовка через серию регулярных выражений, чтобы преобразовать ее в файловую систему, дружественную к slug. С таким подходом я мог бы также сделать это вручную,
2. Я нахожусь на macos, где по какой-то причине пробелы экранируются вместо использования кавычек, как это делают все остальные, так что вот откуда я взял экранирующий подход. Честно говоря, я не знаю, будет ли экранирование пробелов работать в Linux, потому что я никогда не видел, чтобы пробелы экранировались где-либо, кроме macos.