Как мне написать псевдоним bash, который заменяет! $ Последним словом предыдущей команды?

269
Greg Bacon

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

Например:

cpodin /foo/bar/baz vim !$/SHA1SUM 

Как сделать, чтобы последняя команда называлась псевдонимом, fixshaкоторый не принимает аргументов и редактирует SHA1SUMв каталоге, названном последним аргументом предыдущей команды? Псевдоним

alias fixsha='vim !$/SHA1SUM' 

приводит к попыткам редактирования !$/SHA1SUMвместо /foo/bar/baz/SHA1SUM.

1

1 ответ на вопрос

2
Greg Bacon

Bash не выполняет раскрытие истории после раскрытия псевдонима, поэтому вы должны сделать это явно, используя history, документированные в Bash History Builtins и приведенные ниже.

history -ps args

  • -p
    Выполните подстановку истории по аргументам и отобразите результат на стандартном выводе, не сохраняя результаты в списке истории.
  • -s
    Аргументы добавляются в конец списка истории как одна запись.

Псевдоним alias fixsha='vim $(history -p !$)/SHA1SUM'будет работать большую часть времени, но не так, как задумано, когда !$расширяется до пути, содержащего пробелы. Добавление двойных кавычек вокруг аргумента пути защитит любые побеги на пустом месте и приведет к получению результата, vim "/foo/bar\ baz/SHA1SUM"а не к желаемому vim /foo/bar\ baz/SHA1SUMили его эквиваленту vim "/foo/bar baz/SHA1SUM".

Таким образом, в дополнение к явному расширению истории, evalтакже необходимо развернуть один слой цитирования.

alias fixsha='eval vim "$(history -p !$)/SHA1SUM"' 

Примечание. Вы можете быть удивлены, узнав, что двойные кавычки в приведенном выше определении псевдонима не нужны. Это связано с тем, что между расширенным значением !$и /SHA1SUMзапуском разбиения слов в bash нет пробела . Тем не менее, мне нравится, когда они там, чтобы подчеркнуть намерение, что это распространяется на один аргумент.