18

Создание алиаса Bash с параметром?

15

Я раньше использовал CShell (csh), который позволяет создавать псевдонимы с параметрами. Нотация выглядела примерно так:

alias junk="mv \\!* ~/.Trash"

В Bash, похоже, это не работает. Учитывая, что Bash предлагает множество полезных функций, я предполагал, что эта возможность уже реализована, но мне интересно, как именно это можно сделать.

5 ответ(ов)

29

В Bash алиас не принимает параметры напрямую. Вам нужно создать функцию.

Команда alias не может принимать параметры, но функция может вызываться так же, как алиас. Например:

myfunction() {
    # выполняем действия с параметрами, такими как $1
    mv "$1" "$1.bak"
    cp "$2" "$1"
}

myfunction old.conf new.conf # вызывает `myfunction`

Кстати, функции Bash, определенные в вашем .bashrc и других файлах, доступны как команды в вашем оболочке. Поэтому, например, вы можете вызвать ранее определённую функцию так:

$ myfunction original.conf my.conf
3

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

bash$ myfunction() { mv "$1" "$1.bak" && cp -i "$2" "$1"; }

bash$ myfunction original.conf my.conf

Не забудьте добавить точку с запятой перед закрывающей фигурной скобкой. Аналогично для самого вопроса:

csh% alias junk="mv \\!* ~/.Trash"

В bash это можно сделать так:

bash$ junk() { mv "$@" ~/.Trash/; }

Или:

bash$ junk() { for item in "$@" ; do echo "Тращу: $item" ; mv "$item" ~/.Trash/; done; }
2

Вопрос задан неверно. Вы не можете создать псевдоним, который будет принимать параметры, потому что alias просто добавляет второе имя для уже существующей команды. Функциональность, которую вы ищете, можно реализовать с помощью команды function, чтобы создать новую функцию. Вам не нужно делать псевдоним функции, так как у нее уже есть имя.

Возможно, вы хотите что-то вроде этого:

function trash() { mv "$@" ~/.Trash; }

Вот и все! Вы можете использовать параметры $1, $2, $3 и так далее, или просто передать их все через $@.

2

Кратко: Сделайте это вместо этого

Гораздо проще и читаемее использовать функцию, чем алиас, для вставки аргументов в середину команды.

$ wrap_args() { echo "до $@ после"; }
$ wrap_args 1 2 3
до 1 2 3 после

Если вы прочитаете дальше, то узнаете вещи, которые вам не нужны знать о обработке аргументов в shell. Знание может быть опасным. Просто добейтесь необходимого результата, прежде чем темная сторона навсегда овладеет вашей судьбой.

Уточнение

Алиасы в bash на самом деле принимают аргументы, но только в конце:

$ alias speak=echo
$ speak hello world
hello world

Вставка аргументов в середину команды через alias действительно возможна, но это выглядит не очень аккуратно.

Не пытайтесь это повторить, детишки!

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

Рабочее решение — передать аргументы, которые принимает alias, только в конце, в обертку, которая вставит их в середину и затем выполнит вашу команду.

Решение 1

Если вы категорически против использования функции, вы можете сделать так:

$ alias wrap_args='f(){ echo до "$@" после;  unset -f f; }; f'
$ wrap_args x y z
до x y z после

Вы можете заменить $@ на $1, если вам нужен только первый аргумент.

Объяснение 1

Это создает временную функцию f, которой передаются аргументы (обратите внимание, что f вызывается только в самом конце). Команда unset -f удаляет определение функции после выполнения алиаса, так что она не останется.

Решение 2

Вы также можете использовать подпроцесс:

$ alias wrap_args='sh -c '\''echo до "$@" после'\'' _'

Объяснение 2

Алиас формирует команду, подобную:

sh -c 'echo до "$@" после' _

Комментарии:

  • Плейсхолдер _ обязателен, но может быть чем угодно. Он устанавливается в $0 sh и необходим, чтобы первые пользовательские аргументы не были съедены. Демонстрация:

    sh -c 'echo Съедено: "$0" Печатаем: "$@"' алкоголь пьяное бормотание
    Съедено: алкоголь Печатаем: пьяное бормотание
    
  • Одинарные кавычки внутри одинарных кавычек обязательны. Вот пример, показывающий, что это не работает с двойными кавычками:

    $ sh -c "echo Съедено: $0 Печатаем: $@" алкоголь пьяное бормотание
    Съедено: -bash Печатаем:
    

    Здесь значения $0 и $@ интерактивной оболочки будут заменены в двойных кавычках до того, как они будут переданы в sh. Вот доказательство:

    echo "Съедено: $0 Печатаем: $@"
    Съедено: -bash Печатаем:
    

    Одинарные кавычки гарантируют, что эти переменные не будут интерпретированы интерактивной оболочкой и будут переданы в sh -c как есть.

    Вы могли бы использовать двойные кавычки и \$@, но лучшей практикой является экранирование аргументов (так как они могут содержать пробелы), а \"\$@\" выглядит еще менее привлекательно, но может помочь вам выиграть конкурс на неразборчивость, где растрепанные волосы являются обязательным условием для участия.

0

В ответ на ваш вопрос, существует "технически сложный" способ создать функцию внутри алиаса:

$ alias mkcd='_mkcd(){ mkdir "$1"; cd "$1";}; _mkcd'
             ^        *      ^  ^     ^  ^         ^

Здесь важно правильно расставить одинарные и двойные кавычки. Тем не менее, на самом деле нет особой необходимости писать функцию внутри алиаса, так как можно просто определить функцию обычным образом. Такой подход не дает преимущества, кроме как предотвращения перезаписи функции при загрузке других скриптов, в которых может быть определена функция с тем же именем.

Предпочтительный способ будет выглядеть так:

$ mkcd(){ mkdir "$1"; cd "$1";};

Это более читабельно и понятно.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь