Bash aliasok és változókkal, függvényekkel helyettesítésük

Laptop billentyűzet képe a pixabay.com-ról

A korábbi cikkekben előkerültek már a függvények, amikkel egy fájlon belül is önálló egységekre bonthatók a nagyobb szkriptek, illetve egyfajta függvénykönyvtárként bárki számára átadhatók. Ez nagyon jó, de néha talán feleslegesnek tűnik egy egyszerűbb feladatra. Ilyenkor jöhetnek jól az álnevek, avagy aliasok. Más részt viszont az alias sem való mindenre és nem is minden esetben alternatíva függvényre vagy változóra. Ebben a cikkben megmutatom mindhárom előnyét, hátrányát, hogy mindig a legmegfelelőbbet választhasd.

Tartalomjegyzék

Alapok

[Tartalom]

Egy nagyon egyszerű "sayHello" függvényre példa az alábbi:

function sayHelloTo() {
  echo Hello $1
}
# call:
sayHelloTo "John"
# output:
# Hello John

Ennél persze jóval összetettebb függvényeket lehet készíteni. Ezzel szemben egy alias deklarációja azonos kimenettel alább látható:

alias sayHelloAgainTo="echo Hello"
# call:
sayHelloAgainTo "John"
# output:
# Hello John

Látható, hogy az álnév deklarációjában nem használtam argumentumot, mivel nincs is rá mód. Itt csupán arról van szó, hogy egy rövidebb kulcsszóval egy hosszabb utasítást tudok lefuttatni. Gyakorlatilag olyan, mintha egy változót deklaráltam volna az alábbi módon:

sayHelloAgainTo="echo Hello"
# call:
$sayHelloAgainTo "John"
# output:
# Hello John

Változó és alias között látszólag nincs különbség a szintaktikán kívül, de hamarosan megmutatom, hogy mégis van.

Listázás, deklaráció

[Tartalom]

Ha te magad nem is deklaráltál még aliast, jó eséllyel már használtad. Linuxon az ls paranccsal fájlokat, mappákat listázhatsz parancssorból, de mivel gyakran van rá szükség, aliasként más neveken is elérhető lehet különböző paraméterezéssel. Az alias parancsot paraméterek nélkül futtatva az összes deklarált álnevet megjelenítheted. Esetemben az alábbi a kimenet:

alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
alias sayHelloAgainTo='echo Hello'

Itt persze a legutolsó az általam hozzáadott. Előtte viszont láthatók az ls parancs álnevei. Ezeken kívül az első, azaz az alert külön figyelmet érdemel, mivel egy elég komplex álnévről van szó. Nézzük is meg közelebbről a többi parancs kiszűrésével az alias-nak paraméterként az álnevet átadva:

alias alert

Kimenet:

alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

Ahogy a változóknál, úgy az aliasoknál is nehezítő körülmény, hogy az összetettebb értékeket idézőjelbe kell tenni. Az idézőjelben levő értékeket egy IDE kisebb eséllyel fogja színezni és már megírni is nagyobb figyelmet igényel az idézőjelek és speciális karakterek miatt.

A függvényektől eltérően nincsenek argumentumok. Maximum a parancs végére lehet illeszteni további értékeket, ahogy azt a sayHelloAgainTo aliasban tettem.

Alias helyettesítése változóval

[Tartalom]

Bár az első példa alapján teljesen úgy működik egy változóba ágyazott kód, mint az aliasban, de abban a példában szándékosan nem használtam változót a definíción belül. Az alias lényege ugyanis, hogy a benne levő értékek úgy lesznek értelmezve a meghívás pillanatában, mint ahogy az a definícióban szerepel. Mintha egy az egyben bemásoltam volna az idézőjelek közötti részt. Így aztán lehet benne pipe (|) vagy hibakódfüggően láncolhatók az utasítások (&& és || karakterekkel). Ha ugyanazt változóban adod meg, az utasítás első szóköz előtti része lesz a parancs és minden más annak csak argumentuma, stringként kezelve és változókat nem kiértékelve.

Példa:

alias userInfo='echo "User:" && echo $USER'
userInfo
# output:
# User:
# takacsakos

userInfo='echo "User:" && echo $USER'
$userInfo
# output:
# "User:" && echo $USER

Látható, hogy nem csak az && karaktereket nem értelmezte a változó esetén, de még a $USER változót sem helyettesítette be az értékére, mivel az egész parancsot aposztrófok közé tettem, ami az aliasoknál nem csak nem hiba, de általában javasolt is. Ellenkező esetben már a deklarációnál kiértékelné a változót, pedig időközben az megváltozhat.

Az álnevek funkcionalitását változókkal az eval kulcsszó segítségével lehet elérni.

userInfo='echo "User:" && echo $USER'
eval $userInfo
# output:
# User:
# takacsakos

Változót viszont érdemes idézőjelbe tenni az eval használatával, míg anélkül idézőjelbe tett változó a teljes, szóközökkel tűzdelt utasítást próbálná a Bash egyetlen programfájl neveként értelmezni. Ez pedig nyilván nem cél. Az eval paramétereként viszont a sortöréseket tartalmazó utasítás rendeződne egyetlen sorba idézőjel nélkül, ami szintén hibás működéshez vezethet. Példák alább:

userInfo='
  echo "Username:"
  echo $USER
'

eval $userInfo
# output:
# Username: echo takacsakos

eval "$userInfo"
# output:
# Username:
# takacsakos

alias userInfo='
  echo "Username:"
  echo $USER
'

# output:
# Username:
# takacsakos

Az aliasnak semmi gondja nincs a többsoros kóddal. Ez azért van, mert pontosan olyan, mintha ott helyben bemásoltad volna a parancssorba a tartalmát. A változókról és idézőjelekről pedig írtam korábban a Bash argumentumok kapcsán, ahol ez ennél bonyolultabb.

Alias használata szkriptekben

[Tartalom]

Fontos ellentét alias és függvény között, hogy a függvényt épp gyakrabban írjuk szkriptekben alkalmazáshoz, mint interaktív shellben futtatásra, míg az aliasoknál ez fordítva van. Bár maga az alias paraméter nélküli parancs szkriptben is listázza a szkriptben definiált aliasokat, viszont azok használatához egy speciális kapcsolóra van szükség. Az alábbi utasítás például az userinfo: command not found hibaüzenetet adná:

#!/bin/bash

set -eu

alias userInfo='
  echo "User:"
  echo $USER
'

alias
userInfo
# output:
# alias userInfo='
#   echo "User:"
#   echo $USER
# '
# ./test.sh: line 12: userInfo: command not found

Most pedig nézzük a helyes megoldást:

#!/bin/bash

set -eu

shopt -s expand_aliases

alias userInfo='
  echo "User:"
  echo $USER
'

alias
userInfo
# output:
# alias userInfo='
#   echo "User:"
#   echo $USER
# '
# User:
# takacsakos

Argumentumok aliasokkal

[Tartalom]

Úgy tűnthet, félrebeszélek, mivel kijelentettem, hogy nincsenek argumentumok aliasokban. Ez így is van, viszont egy kis trükkel a sudo használatról szóló cikkben említett megoldással lehet hasonlót megvalósítani:

alias lsroot="bash -c 'ls \$1 /' --"
lsroot -la

A fenti kód például bárhonnan a gyökérkönyvtár tartalmát fogja listázni, viszont paraméterben átadhatók neki az ls parancs kapcsolói.

Azt hiszem, azért érezhető, hogy ezen a ponton már nem éri meg aliast használni.

Végszó

[Tartalom]

Jó tudni a változókról, függvényekről és aliasokról is, viszont komolyabb kódhoz azért szükség lesz függvényre. Egyetlen hátrányuk talán, hogy az opcionális paraméterátadást külön le kell kezelni, miközben az aliasoknál a meghívás pillanatában opcionális a végére fűzendő paraméterek átadása. Az utasítás más pontjaira viszont csak trükközéssel van mód, ami érdekes, de lehetőleg kerülendő. A változókról nem a kód futtatás jutna eszébe az embernek, de Bash-ben ez az alap működés része. Az eval kulcsszó is segíthet összetettebb utasításnál, ami gyakorlatilag úgy működik, mint egy alias, viszont nem fog ütközni adott esetben függvény deklarációkkal, programnevekkel, ráadásul nagyon egyszerű függvényen belül lokális alias-szerű megoldást írni. Aliast viszont hiába definiálsz egy függvényben, az csak a függvény lefutása után lesz elérhető, mégpedig globálisan.

Ha tehát egy mód van rá, használj függvényeket. Szkriptekben mindenképpen. Ha függvényen belül szeretnél kisebb kódrészletet újra felhasználni, talán akkor is megteszi egy új globális függvény, de ha nagyon nem szeretnéd, még mindig rejtheted változókba a kódsorokat. Függvényen kívül használhatsz aliast, de ne feledkezz meg az expand_aliases opcióról. Interaktív shellben viszont bevett szokás aliasokat használni programok alapértelmezett paraméterezésének megváltoztatására.

Továbbra is, mint mindig, várom a megjegyzéseket, véleményeket, hibajelentéseket bármely csatornán. És ne feledd, minden vélemény, like, de még az építő jellegű kritika is számít, sőt, újabb és újabb cikkeket szül. Kövess bátran Facebookon, ha még nem teszed, és... ne tartsd titokban az oldal létezését barátaid előtt :)

Források

[Tartalom]

Megosztás/Mentés