аналогично существующему $_
, который, как я узнал, обозначает !-1:$
, я хотел бы создать псевдонимы для $__
, $___
и так далее, которые ссылаются на 2-ю или 3-ю -последнюю команду. Я пробовал добавлять
alias "$__"='!-2:$'
в моем .zshrc.local
. Если возможно, я хотел бы написать zsh-функцию, которая возвращает 1-й аргумент n-й последней команды на основе количества подчеркиваний.
arch linux kernel 5.1.4-arch
zsh 5.7.1 (x86_64-pc-linux-gnu)
решение1
Эта функция уже существует
Вам не нужно ничего сложного, чтобы получить доступ к последнему слову предыдущих команд. Просто нажмите ESC-.
(ie Alt+ .) или ESC-_
(ie Alt+ _). Это вызовет команду редактораinsert-last-word
, который вставляет последнее слово из предыдущей командной строки. Нажмите клавишу еще раз, чтобы получить последнее слово из командной строки перед этим, и так далее. Если вы нажмете ESC-.
один раз слишком много, используйте C-_
(отменить), чтобы вернуться к слову, которое у вас было только что.
По умолчанию эта команда не привязана к клавише в режиме vi, но вы можете привязать ее с помощью bindkey
.
Вы можете передать числовой аргумент, чтобы получить другое слово: положительный, чтобы начать справа (1 — последнее слово), ноль или отрицательный, чтобы начать слева (0 — первое слово, которое обычно является именем команды, 1 — слово после него, которое является первым аргументом и т. д.). Например, ESC . ESC - ESC 1 ESC .
вставляет первый аргумент предпоследней команды.
Возможны многочисленные вариации этой команды путем определения собственного виджета вокруг zle insert-last-word
. Zsh поставляется сcopy-earlier-word
иsmart-insert-last-word
которые вы можете использовать как есть или в качестве примеров кода.
Если вы действительно хотите $__
расширить до последнего слова предпоследней команды, я дам несколько решений ниже, но сначала мне нужно объяснить, что происходит.
Почему ваша попытка не сработала
Во-первых, вы не определяете то, что, как вы думаете, вы определяете. alias "$__"=…
определяет псевдоним, имя которого является текущим значением переменной __
на момент выполнения определения псевдонима. Это, вероятно, пусто, поэтому вы выполняете, alias ='!-2:$'
который ищет команду, вызванную '!-2:$'
на пути поиска (=
расширениечасть расширения имени файла). Чтобы определить псевдоним с именем $__
, необходимо передать $__
команду alias, например, с помощью alias '$__'=…
или alias \$__=…
.
Во-вторых, псевдоним раскрывается только в командной позиции, т.е. как первое слово команды (после любых начальных назначений переменных и перенаправлений). Для того, чтобы этот псевдоним был полезен, он должен бытьглобальный псевдоним:alias -g '$__'=…
В-третьих, этот псевдоним не принесет никакой пользы, поскольку расширение псевдонима происходит после расширения истории.
darkstar
darkstar% alias -g '$__'='!-2:$'
darkstar% echo $__
!-2:$
$_
не «стоит за» !-1:$
. $_
и !-1:$
являются двумя способами доступа к одной и той же информации в общих случаях. Вы можете сказать, что $_
«является псевдонимом» !-1:$
, или наоборот, что !-1:$
«является псевдонимом» $_
, но это использование «псевдонима» в его общеанглийском смысле, а не в техническом смысле псевдонимов оболочки, и это неточно, потому что эти два не всегда имеют одинаковое значение. !-1:$
являетсяистория расширение( !
) конструкция, которая расширяется доПоследнее слово( :$
) принадлежащийпредыдущая командная строка( -1
). $_
этоparameter expansion
используя параметр_
который оболочка устанавливает в последний аргумент предыдущей команды. Это имеет значение, если вы запускаете командные строки, которые не являются одной простой командой, например:
darkstar% for x in 1 2 3; do echo $x; done
1
2
3
darkstar% echo $_ is not !-1:$
echo $_ is not done
3 is not done
darkstar% echo $_ and !-1:$ are different; echo $_ and !-1:$ are different
echo $_ and done are different; echo $_ and done are different
done and done are different
different and done are different
Определение $__
по команде
Вы можете определитьфункция ловушкиназываетсяTRAPDEBUG
который запускается перед выполнением каждой команды. Запомните текущее значение $_
(обратите внимание, что вам нужно сделать это в первую очередь, потому что первая команда внутри ловушки перезапишет _
), затем «сдвиньте» переменные с несколькими подчеркиваниями.
darkstar% TRAPDEBUG () { _0=$_; ___=$__; __=$_1; _1=$_0; }
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_,$__,$___
three,two,one
$_1
не всегда будет таким же, как $_
, поскольку отладочная ловушка не срабатывает в тех же самых обстоятельствах, которые вызывают _
ее установку, но она довольно близка.
Определение $__
в командной строке
Вы можете зарегистрироватьфункция крючкадля запуска до или после ввода командной строки. В этом случае либоprecmd
илиpreexec
. Они запускаются до и после выполнения команды соответственно.
preexec_set_underscore_variables () {
___=$__
__=$_1
_1=$historywords[1]
}
preexec_functions+=(preexec_set_underscore_variables)
я используюhistorywords
чтобы получить последнее слово из командной строки. Я сохраняю его в , _1
потому что _
уже занято. И функция «сдвигает» переменные истории последнего слова на единицу.
darkstar% echo one
one
darkstar% echo two
two
darkstar% echo three
three
darkstar% echo $_ $__ $___
three two one