Как получить заполнение клавишей Tab при использовании фигурных скобок в Bash

[1130170] Если один диск уже полностью исчез, то дубликат не нужен.


Если другой диск не работает, то можно скопировать этот диск, используя [1130552]ddrescue[1130553], а затем посмотреть, что осталось, используя дубликат.

На этом этапе вы имеете молчаливое повреждение данных; с помощью [1130554]ddrescue[1130555] вы можете найти поврежденные файлы, имея запись о том, какие области не могли быть прочитаны, и используя [1130556]filefrag[1130557] определить, какие файлы имеют расширения в этих областях.

Может быть проще скопировать файлы с поврежденного массива, при условии, что он все еще работает и работает вообще. Это немного опасно, хотя, поскольку такая случайная копия доступа на диск более напряжена, чем линейная [1130558]ddrescue[1130559], и если диск умрет полностью, то все пропало.

2
26.01.2015, 23:52
5 ответов

С помощью paste

 paste -d'\n' - - /dev/null <file
-121--19510-

Скобки (которые по определению являются «фигурными») в данном контексте относятся к списку фрагментов текста, разделенных запятыми. Хотя он чаще всего используется для имен файлов, он расширяется перед обработкой расширений имен файлов. Поэтому нет возможности окончательного расширения, поскольку bash не может знать, действительно ли вы вводите имя файла или нет.

-121--150633-

Существует два способа интерпретации вопроса: вы хотите завершить, пока вы вводите имена перед закрытием } (фактически делать завершения файлов в другом каталоге); или необходимо развернуть и заменить (допустимые) имена после закрытия } . {} расширяет все опции, в отличие от globbing, который расширяет существующие имена файлов, хотя использует «», а не космос.

При использовании bash ожидаемым способом создания списка слов является {} :

cp ~/html/{foo,bar.txt,whatever}  ...

Существует два варианта: связывание привязки клавиши readline с функцией оболочки или программируемое завершение.

Подход readline дает вам возможность полностью переписать текущую команду, но проблема в том, что она не маркирует текущую командную строку, поэтому у вас есть нетривиальная проблема синтаксического анализа.

Программируемое завершение маркирует командную строку, но можно только изменить/заменить текущее слово, что означает, что невозможно (легко) сохранить префикс path/{ во время редактирования.

Единственной связанной встроенной функцией bash является функция readline shell-expand-line для bash, которая предназначена для выполнения «всех расширений слова shell». По умолчанию она привязана к \M-\C-e (Esc \C-e ). Можно разумно ожидать, что это расширение будет все из семи типов расширения, указанных на странице man (bash-4.3):

 Расширение выполняется в командной строке после его разделения на
слова. Существует семь видов расширения: расширение раскосов,
расширение тильды, параметр и переменное расширение, командует substitu ‐
тион, арифметическое расширение, разделение слов и расширение пути.

Вы можете поэкспериментировать с помощью ввода (без нажатия кнопки Return)

echo {1..2} ~root $0 $LANG `echo foo` $((1+2) "a b" /etc/p[aeiou]*

, а затем Meta Ctrl E (или ESC + Ctrl E , если вы используете мета-дефибрированную клавиатуру).

Ни первое, ни последнее (скобка и путь) расширения не работают для меня, поэтому документация и реализация не вполне соответствуют IMHO.

Ниже приведено не полное, а рабочее решение с использованием вкладки для расширения. Необходимо убедиться, что используется правильный синтаксис для раскоса, хотя, в частности, с запятой, чтобы разделить элементы, а не космос.

function _expand() {
   [[ -z "${READLINE_LINE}" ]] && return
   eval local aa=( ${READLINE_LINE} )       # not-quoted, eval needed
   [[ ${#aa} -eq 0 ]] && return             # parse problem
   printf -v READLINE_LINE "%s " "${aa[@]}"
   READLINE_POINT=${#READLINE_LINE}         # eol, predictable at least
}

bind -x '"\C-_":_expand'

При этом Ctrl _ связывается с функцией bash, которая использует eval для заполнения массива, вызывая все обычные расширения (как указано выше, не включая историю), а затем перестраивает командную строку.

Начните ввод, нажмите Ctrl _ , когда вы хотите что-то развернуть, и Вернитесь , как обычно, когда будете готовы.

Это более мощное, чем tab, но менее точное, поскольку оно расширяет всю входную строку. Есть несколько случаев, когда это не расширится, как надеялись, в частности, когда различные метасимволы оболочки путают простую логику оценки .

Предложение Гилле zsh стоит посмотреть, а не сверхинженерное решение.

0
27.01.2020, 22:56

Скобки (которые по определению являются "фигурными") в этом контексте относятся к списку фрагментов текста, разделенных запятыми. Хотя чаще всего он используется для имен файлов, он расширяется до обработки расширений имен файлов . Следовательно, не существует окончательной возможности расширения, потому что bash не может знать, действительно ли вы набираете имя файла или нет.

0
27.01.2020, 22:56

из Человек Bash :

COMP_WORDBREAKS
       The  set  of  characters  that  the readline
       library treats as word separators when  per‐
       forming word completion.  If COMP_WORDBREAKS
       is unset, it loses its  special  properties,
       even if it is subsequently reset.

Я думал, что это было интересно, поэтому я сделал:

printf %q\\n "${COMP_WORDBREAKS}"

... посмотреть на его значение по умолчанию. Это получил меня:

$' \t\n"\'@><=;|&(:'

Итак, я понял, почему бы не ...?

$ COMP_WORDBREAKS="{}$COMP_WORDBREAKS"
$ {/<TAB><TAB>

... где Часть представляет, что мой нажав нажав И я видел:

$ {/
bin/      esp/      lib/      opt/      run/      sys/      usr/      
boot/     etc/      lib64/    proc/     sbin/     testuser/ var/      
dev/      home/     mnt/      root/     srv/      tmp/

так что было аккуратно. Я тогда сделал:

$ COMP_WORDBREAKS=${COMP_WORDBREAKS#??}
$ {/<TAB><TAB>

... и ничего не произошло.

0
27.01.2020, 22:56

В терминале Ubuntu (16.04 )вы можете выполнить Ctrl + { , а затем { и автоматически дополнить фигурные скобки файлами в каталоге. Он использует запятые вместо пробелов для разделения файлов. Например, каталог, содержащий эти файлы : file.cpp file.h file.i file.py file_wrap.cxx

... будет автоматически завершено до этого : $ cp file{.{cpp,h,i,py},_wrap.cxx}

2
27.01.2020, 22:56

Я предоставляю диагностический инструмент, который позволяет OP напрямую наблюдать за поведением завершения строки после табуляции и для сравнения поведением синтаксического анализа после возврата. После наблюдения и анализа мы можем сделать вывод, что, хотя написание функции завершения строки для завершения функции фигурных скобок может быть возможно -, это было бы бессмысленно из-за ограничения bash на подавление любой дальнейшей функции завершения строки после фигурных скобок.

Следующий скрипт bash включает диагностику:

#!/bin/bash

confirm_args(){
    logger -t "confirm_args" -- "#=${#}"
    for index in `seq 0 ${#}` ; do
        eval item=\$$index
        logger -t "confirm_args" -- "[$index] ${item}"
    done    
}

_foo_completion(){
    logger -t "_foo_completion" -- "COMP_CWORD=${COMP_CWORD}" 
    logger -t "_foo_completion" -- "#COMP_WORDS=${#COMP_WORDS[@]}"
    for index in `seq 0 $((${#COMP_WORDS[@]}-1))` ; do
        logger -t "_foo_completion" -- "[$index] ${COMP_WORDS[$index]}"
    done
}
declare -f _foo_completion
complete -F _foo_completion "foo"
alias foo=confirm_args

Я сделал это доступным как сутьfoo-completion.sh.

Скопируйте и вставьте в файл /tmp/foo-completion.sh.

Создать два фиктивных файла

touch /tmp/a.{1,2}

Чтобы диагностика работала правильно, loggerдолжен записать в системный журнал. Затем OP сможет просматривать диагностические выходные данные, следуя файлу системного журнала. Если OP работает systemd, его можно просмотреть, открыв новое окно и введя

sudo journalctl -f

Активировать завершение строки и диагностический выход:

source /tmp/foo-completion.sh

Обратите внимание, что _foo_completionНЕ выполняет никакого завершения, поэтому кандидаты не возвращаются пользователю. Все, что он делает, это показывает, какие данные передаются функции завершения строки.

Протестируйте некоторые входы и посмотрите на выходы:

ВХОД 1

foo a.*[SPACE][TAB]

ВЫХОД

Jul 23 12:10:34 ub18 _foo_completion[17672]: COMP_CWORD=2
Jul 23 12:10:34 ub18 _foo_completion[17673]: #COMP_WORDS=3
Jul 23 12:10:34 ub18 _foo_completion[17675]: [0] foo
Jul 23 12:10:34 ub18 _foo_completion[17676]: [1] /tmp/a.*
Jul 23 12:10:34 ub18 _foo_completion[17677]: [2]

ВХОД 2

foo a.*[SPACE][RETURN]

ВЫХОД

Jul 23 12:19:43 ub18 confirm_args[18487]: #=2
Jul 23 12:19:43 ub18 confirm_args[18489]: [0] bash
Jul 23 12:19:43 ub18 confirm_args[18490]: [1] /tmp/a.1
Jul 23 12:19:43 ub18 confirm_args[18491]: [2] /tmp/a.2

ВХОД 3

foo a.{1,2}[SPACE][TAB]

ВЫХОД

ПРИМЕЧАНИЕ -нет выхода!

ВХОД 4

foo a.{1,2}[SPACE][RETURN]

ВЫХОД

Jul 23 12:28:42 ub18 confirm_args[19098]: #=2
Jul 23 12:28:42 ub18 confirm_args[19100]: [0] bash
Jul 23 12:28:42 ub18 confirm_args[19101]: [1] /tmp/a.1
Jul 23 12:28:42 ub18 confirm_args[19102]: [2] /tmp/a.2

Анализ

В «INPUT 1» *передается функции завершения строки как литерал '*'. Однако в «INPUT 3» функция завершения строки даже не вызывается. По-видимому, фигурные скобки заставляют bash подавлять любые дальнейшие вызовы функции завершения строки.

С другой стороны,в случаях синтаксического анализа после [RETURN] INPUT 2 и INPUT 4 bash расширяет оба случая a.*и a.{1,2}до одного и того же результата.

Еще один тест:

ВХОД 5

foo a.{[TAB]

ВЫХОД

Jul 23 12:56:52 ub18 _foo_completion[21059]: COMP_CWORD=1
Jul 23 12:56:52 ub18 _foo_completion[21060]: #COMP_WORDS=2
Jul 23 12:56:52 ub18 _foo_completion[21062]: [0] foo
Jul 23 12:56:52 ub18 _foo_completion[21063]: [1] /tmp/a.{

Анализ

В «INPUT 5», без пробела перед вкладкой, bash ВЫПОЛНЯЕТ завершение строки вызова. Таким образом, завершение строки теоретически может вернуть одного кандидата

/tmp/a.{1,2}

, что должно привести к автозавершению -(, хотя я не проверял ).

Проблемас этим заключалась бы в том, чтодальнейшиефайлы не могли быть добавлены с завершением строки, потому что фигурные скобки подавляют завершение строки.

Тестирование с уже существующей функцией завершения строки, например,

ПРОВЕРКА ВХОДА

ls /tmp/a.{[TAB][TAB][TAB][TAB][TAB][TAB]

ВЫХОД

(ничего)

, кажется, поддерживает тезис о том, что не стоит поддерживать завитки в функции завершения строки до тех пор, пока/если bash не подавляет завершение строки после завитков.

РЕДАКТИРОВАТЬ :Поиграв с методом [CTRL]{{, описанным в этом ответе , я нашел его завершенным, и (иногда )можно было использовать функцию завершения по умолчанию для добавить больше файлов. Однако после этого не было возможности продолжить использование исходной функции _foo_completion, что может быть или не быть ограничением в зависимости от варианта использования.

0
23.07.2020, 20:11

Теги

Похожие вопросы