Як продовжити баш псевдоніми


11

Як створити псевдонім, який насправді поширює інший псевдонім з такою ж назвою в Bash?

Чому:

Раніше я GREP_OPTIONSналаштовувався на .bashrcщось подібне:

GREP_OPTIONS="-I --exclude=\*~"

У мене також був сценарій (скажімо так setup-java.sh), який я б закликав, перш ніж працювати над деякими проектами Java. Він буде містити рядок:

GREP_OPTIONS="$GREP_OPTIONS --exclude-dir=classes"

Якщо я також використовую Sass, я б зателефонував, setup-sass.shякий містить рядок:

GREP_OPTIONS="$GREP_OPTIONS --exclude-dir=\*/.sass-cache"

Але GREP_OPTIONSзастаріле і, мабуть, стандартне рішення - це або створити псевдонім, або якийсь сценарій ...


Що з функціями bash?
Jakuje

2
Я цілком згоден - використання функції набагато кращий варіант, ніж псевдонім.
Чарльз Даффі

Відповіді:


13

Bash зберігає значення псевдонімів у масиві під назвою BASH_ALIASES :

$ alias foo=bar
$ echo ${BASH_ALIASES[foo]}
bar

З допомогою розширення параметрів ми можемо отримати псевдонім останнього набору (якщо він існує) або значення за замовчуванням:

alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~"

Тепер просто зробіть це setup-java.sh:

alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~  --exclude-dir=classes"

... і нарешті setup-sass.sh:

alias grep="${BASH_ALIASES[grep]:-grep} -I --exclude=\*~ --exclude-dir=\*/.sass-cache"

Якщо три рядки викликаються, ми отримуємо те, що хочемо:

$ echo ${BASH_ALIASES[grep]:-grep}
grep -I --exclude=\*~ -I --exclude=\*~ --exclude-dir=classes -I --exclude=\*~ --exclude-dir=\*/.sass-cache

13

aliases ланцюжок, якщо ви закінчите їх пробілами.

alias print='printf %s\\n ' hey='"hello, fine fellow" '
print hey

hello, fine fellow

Ви можете писати цілі сценарії таким чином, якщо ви досить божевільні. У будь-якому випадку, якщо ви хочете розширити псевдонім, тоді просто переконайтеся, що псевдонім, який ви хочете розширити, закінчується в пробілі, і торкніться іншого.

alias grep='printf "%s " -I --exclude=\*~ '    \
      exdir=' --exclude-dir=classes '          \
      exsass='--exclude-dir=\*/.sass-cache '
grep exdir exsass exdir exsass

-I --exclude=*~ --exclude-dir=classes --exclude-dir=*/.sass-cache --exclude-dir=classes --exclude-dir=*/.sass-cache

7
Це жахливо красиво.
користувач1717828

Ого, це дивовижно. Я не знав цього (і, мабуть, не дуже використовувати його, тому що я думаю, що це суперечить правилу ясності ), але це приємно знати! Питання, однак: Чому пробіл на початку exdir? (Це лише для вирівнювання з естетичних причин?)
Wildcard

2
@Wildcard: fnmatch(){ alias fnmatch='case $1 in '; while "${1:+:}" 2>&-; do eval 'fnmatch pattern list ;; esac'; shift; done; unalias fnmatch; }; alias pattern='${1:+*}) ' list=': do stuff '; fnmatch "$@". Якщо це зробити, aliasesви можете використовувати розширення шаблонів більш прямо та безпечніше. Вам потрібен другий контекст ж / evalпри виклику з функції, але це не по своїй суті небезпечно, поки patternі listназви контролюються вами. Вони можуть зламатися лише в більшості випадків, навіть якщо їх немає, якщо хтось зловмисник свідомо правильно закінчить ваш case.
mikeserv

1
Я використовую цю схему в моєму .bashrc:, alias sudo='sudo 'це дозволяє мені викликати всі свої відчужені команди після a sudo. Без місця це не спрацювало б
arainone

1
@Wildcard - Я не дуже виступав за таке використання, але це правда, що ти можеш, і також правда, що ти повинен спробувати хоч трохи божевільний.
mikeserv

2

Функція - кращий варіант, ніж розширюваний псевдонім тут.

grep_options=( )
grep() {
  exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"
}

Таким чином, у вас є два варіанти додати параметри до середовища:

  • Змінити grep_optionsмасив; це правильно підтримує параметри з пробілами, буквальними глобусними символами та іншими кутовими справами:

    grep_options+=( --exclude-dir=classes --exclude-dir='*/.sass-cache' )
  • Використовуйте традиційну GREP_OPTIONSскалярну змінну, незважаючи на її підводні камені (див. BashFAQ # 50, щоб зрозуміти деякі з них):

    GREP_OPTIONS+=' --exclude-dir=classes '

Однак, якщо ви хочете, щоб ваші параметри відображалися grepекземплярами, викликаними поза оболонкою, ні псевдонім, ні функція не будуть робити. Замість цього ви хочете, щоб сценарій обгортки розміщувався раніше у вашому PATH, ніж у реальній grepкоманді. Наприклад:

# in ~/.bash_profile
[[ -e ~/bin ]] && PATH=$HOME/bin:$PATH

... і, в ~/bin/grep:

#!/bin/bash

# load overrides to grep_options on GREP_OPTIONS from local dotfiles
source ~/.bash_profile
source ~/.bashrc

# ...and use them:
exec /usr/bin/grep "${grep_options[@]}" ${GREP_OPTIONS} "$@"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.