передача целых строк в качестве аргументов в fish shell

#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 в NixOS

2. Вы могли бы изучить 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.