Bash Автозаполнение - как передать этот массив для сжатия без значительного пробела, который рушится?
Следующее завершение bash передает массив возможных слов (например, завершений) для compgen.
basenames=("foo" "fu bar" "baz");
COMPREPLY=($(compgen -W "${basenames[*]}" -- "${COMP_WORDS[COMP_CWORD]}"))
Проблема заключается в том, что пробелы в элементах массива не сохраняются, то есть "foo bar" рассматривается как элемент благодаря разбиению слов. Есть ли способ сохранить пробелы, так что отображаются 3 элемента, а не 4?
ИЗМЕНИТЬ
basenames
содержит имена файлов, то есть почти каждый символ (кроме/и\0) разрешен.
РЕДАКТИРОВАТЬ 2
Флаг -W ожидает одно слово, что-то вроде foo bar foobar
. Передача ему нескольких элементов (это то, что будет делать ${basenames[@]}
) не будет работать.
РЕДАКТИРОВАТЬ 3
Изменен массив базовых имен (так что foo
и foo
from foo bar
не будут свернуты).
Использование новой строки для разделения слов работает:
local IFS=$'\n'
COMPREPLY=($(compgen -W "$(printf "%s\n" "${basenames[@]}")" -- ${COMP_WORDS[COMP_CWORD]}"))
Использование \0
не выполняет:
local IFS=$'\0'
COMPREPLY=($(compgen -W "$(printf "%s\0" "${basenames[@]}")" -- ${COMP_WORDS[COMP_CWORD]}"))
Ответы
Ответ 1
Зачем беспокоиться compgen
? Просто добавьте их в COMPREPLY вручную. Следующее выполнит соответствующие имена файлов из /some/path
, безопасно обрабатывая имена файлов.
some_completion_function() {
local files=("/some/path/$2"*)
[[ -e ${files[0]} ]] && COMPREPLY=( "${files[@]##*/}" )
}
Невозможно иметь compgen
имя файла для записи безопасно.
Ответ 2
Возможно, это может сделать:
COMPREPLY=($(compgen -W "$(printf "%q " "${basenames[*]}")" -- "${COMP_WORDS[COMP_CWORD]}"))
Ответ 3
Вы должны почти всегда использовать знак at вместо звездочки для индексирования массива.
COMPREPLY=($(compgen -W "${basenames[@]}" -- "${COMP_WORDS[COMP_CWORD]}"))
из man bash
(или см. справочное руководство Bash):
Если индекс @
или *
, слово расширяется для всех членов имени. Эти индексы отличаются только тогда, когда слово появляется в двойных кавычках. Если слово double-quoted, ${name[*]}
расширяется до одного слова со значением каждого элемента массива, разделенным первым символом специальной переменной IFS, а ${name[@]}
расширяет каждый элемент имени до отдельного слова.
Другими словами, знак знака "выравнивает" массив. Форма звездочки сохраняет его.