So erweitern Sie Bash-Aliase

11

Wie erstelle ich einen Alias, der tatsächlich einen anderen gleichnamigen Alias ​​in Bash erweitert?

Warum:

Früher habe ich mich GREP_OPTIONSauf .bashrcso etwas eingestellt:

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

Ich hatte auch ein Skript (sagen wir mal setup-java.sh), das ich aufrufen würde, bevor ich an einigen Java-Projekten arbeitete. Es würde die Zeile enthalten:

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

Wenn ich auch Sass benutze, würde ich anrufen, setup-sass.shwelches die Zeile enthält:

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

Wurde GREP_OPTIONSaber veraltet und anscheinend besteht die Standardlösung darin, entweder einen Alias ​​oder ein Skript zu erstellen ...

brandizzi
quelle
Was ist mit Bash-Funktionen?
Jakuje
2
Ich stimme vollkommen zu - die Verwendung einer Funktion ist eine viel bessere Option als ein Alias.
Charles Duffy

Antworten:

13

Bash speichert die Werte von Aliasen in einem Array mit dem Namen BASH_ALIASES :

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

Mit der Parametererweiterung können wir entweder den zuletzt eingestellten Alias ​​(falls vorhanden) oder den Standardwert erhalten:

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

Jetzt mach es einfach auf setup-java.sh:

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

... und schließlich auf setup-sass.sh:

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

Wenn die drei Zeilen aufgerufen werden, bekommen wir, was wir wollen:

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

aliases Kette, wenn Sie sie mit Leerzeichen beenden.

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

hello, fine fellow

Auf diese Weise können Sie ganze Skripte schreiben, wenn Sie verrückt genug sind. Wenn Sie einen Alias ​​erweitern möchten, stellen Sie einfach sicher, dass der Alias, den Sie erweitern möchten, in einem Leerzeichen endet, und heften Sie einen anderen an.

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
mikeserv
quelle
7
Das ist schrecklich schön.
user1717828
Wow, das ist großartig. Wusste das nicht (und werde es wahrscheinlich nicht viel benutzen, weil ich denke, dass es gegen die Regel der Klarheit verstößt ), aber es ist schön zu wissen! Frage aber: Warum der Platz am Anfang exdir? (Ist das nur für die Ausrichtung aus ästhetischen Gründen?)
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 "$@". Wenn Sie dies tun, aliaseskönnen Sie die Erweiterungen der Muster direkter und sicherer verwenden. Sie einen zweiten Kontext w / müssen , evalwenn innerhalb einer Funktion aufgerufen, aber es ist nicht von Natur aus unsicher, solange die patternund listNamen , die von Ihnen gesteuert werden . Sie können in den meisten Fällen nur dann brechen, wenn sie es nicht sind, es sei denn, ein Angreifer beendet Ihre wissentlich korrekt case.
Mikesserv
1
Ich verwende dieses Muster in meinem .bashrc: alias sudo='sudo ', damit kann ich alle meine Alias-Befehle nach a aufrufen sudo. Ohne den Platz würde es nicht funktionieren
arainone
1
@Wildcard - Ich habe mich nicht gerade für eine solche Verwendung ausgesprochen, aber es ist wahr, dass Sie es können, und es ist auch wahr, dass Sie zumindest ein bisschen verrückt sein müssen, um es zu versuchen.
Mikeserv
2

Eine Funktion ist hier eine bessere Option als ein erweiterbarer Alias.

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

Auf diese Weise haben Sie zwei Möglichkeiten, der Umgebung Optionen hinzuzufügen:

  • Ändern Sie das grep_optionsArray. Dies unterstützt Optionen mit Leerzeichen, Literal-Glob-Zeichen und anderen Eckfällen korrekt:

    grep_options+=( --exclude-dir=classes --exclude-dir='*/.sass-cache' )
  • Verwenden Sie die traditionelle GREP_OPTIONSskalare Variable trotz ihrer Fallstricke (siehe BashFAQ # 50 , um einige davon zu verstehen):

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

Wenn Sie jedoch möchten, dass Ihre Optionen von grepInstanzen reflektiert werden, die außerhalb der Shell aufgerufen werden, sind weder ein Alias ​​noch eine Funktion ausreichend. Stattdessen möchten Sie ein Wrapper-Skript, das früher in Ihrem PATH als der eigentliche grepBefehl platziert wird. Zum Beispiel:

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

... und in ~/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} "$@"
Charles Duffy
quelle