Kurzusok
/
Bash
Bash
/
Tanterv
/
Csővezetékek és parancslisták
Cs

Csővezetékek és parancslisták ebben a kurzusban: Bash

{one: "1 feladat", other: "%{count} feladat"}

A(z) Csővezetékek és parancslisták fogalomról

Láttuk már, hogyan írjunk egyszerű parancsokat, ahol a parancsot argumentumok követik. Most nézzük meg, hogyan hozhatunk létre összetettebb parancsokat egyszerű parancsok összefűzésével.

Bemenet és kimenet

Mielőtt belekezdünk, egy gyors bevezető a bemenetről és a kimenetről.

A folyamatoknak „szabványos I/O-csatornáik” vannak.

  • Egy folyamat a „stdin” csatornán bemenetet fogadhat.
  • Egy folyamat a „stdout” csatornán kimenetet bocsáthat ki.
  • Egy folyamat a „stderr” csatornán hibakimenetet bocsáthat ki.

A tr parancs erre nagyon tiszta példa. Nem tesz mást, mint beolvassa a szöveget a bemenetéről, karakterátírásokat hajt végre, és a kapott szöveget a kimenetére írja.

A „stdio” csatornák kezeléséről később, a tanterv során még többet olvashatsz.

Csővezetékek

Ez a shell-programozás egyik „legnagyobb dobása”. A csővezetékekkel kifinomult átalakításokat végezhetsz egy szövegfolyamon.

Így állíthatod elő a felhasználók rendezett listáját:

cat /etc/passwd | cut -d : -f 1 | sort

A cső szimbóluma (|) összeköti az egyik parancs kimenetét egy másik parancs bemenetével. A cut a cat kimenetét olvassa, a sort pedig a cut kimenetét.

Advanced
  • Alapértelmezés szerint a csővezeték minden parancsa külön alhéjban fut. (Az alhéj egy gyermekfolyamat, amely az éppen futó shell másolata.)

  • A csővezetékek futtatásának teljesítményköltsége van. Ha hosszú, hasonló parancsokból álló csővezetékeid vannak, fontold meg, hogy egyetlen parancsba vond őket össze. Például a több grep, cut, sed, awk és tr példányt használó csővezetékek a hatékonyság érdekében általában egyetlen awk paranccsá vonhatók össze.

  • A csővezeték kilépési állapota a csővezeték utolsó parancsának kilépési állapota. Ez azt jelenti, hogy ha egy korábbi parancs sikertelen volt, de az utolsó sikeres, akkor az egész csővezeték kilépési állapota nulla.

    Létezik egy shell-beállítás, amely ezt megváltoztathatja; ha a „pipefail” beállítás be van kapcsolva (a set -o pipefail paranccsal), akkor a csővezeték kilépési állapota a következő lesz:

    • nulla, ha minden parancs sikeres, egyébként
    • a csővezetékben lévő parancsok utolsó nem nulla kilépési állapota.

Parancslisták

A parancslista csővezetékek sorozata, amelyeket ; (vagy sortörés), && vagy || választ el egymástól.

  • Az A; B olyan parancslista, ahol a B az A befejeződése után fut le.
  • Az A && B esetén a B csak akkor fut le, ha az A sikeres (nulla állapottal lép ki).
  • Az A || B esetén a B csak akkor fut le, ha az A sikertelen (nem nulla állapottal lép ki).

Egy parancslista kilépési állapota a benne utolsóként lefutott parancs kilépési állapota.

A && és || operátorok láncba fűzhetők, így a következő parancs az előtte lévő parancsok állapota alapján, feltételesen fut le. Például

A && B && C && D || E
  • A B akkor fut le, ha az A sikeres,
  • a C akkor fut le, ha az A és a B is sikeres,
  • a D akkor fut le, ha az A, a B és a C is sikeres,
  • az E akkor fut le, ha az A, B, C vagy D közül bármelyik sikertelen.
Caution

Használd ezeket a logikai operátorokat mértékkel. Gyorsan olvashatatlan kódhoz vagy nehezen átlátható logikához vezethetnek.

Például azt hiheted, hogy ezek ugyanazt jelentik:

if A; then B; else C; fi
A && B || C

A különbség: mikor fut le a C?

  • Az első kódrészletben (az elágazásban) a C csak akkor fut le, ha az A sikertelen.
  • A második kódrészletben a C akkor fut le, ha az A sikertelen, vagy ha az A sikeres, de a B sikertelen!

A parancslisták használata

Íme néhány példa, ahol a parancslisták leegyszerűsíthetik a kódot.

Sorblokkok beolvasása fájlból

Tegyük fel, hogy van egy adatfájlod, amely háromszögekre vonatkozó adatokat tartalmaz, és egy háromszöget három különálló sor ábrázol, amelyek a háromszög oldalait tartalmazzák.

$ cat triangle.dat
3
4
5
9
12
14

Használhatsz egy while-ciklust, amelynek feltétele három külön read parancs:

while read a && read b && read c; do
    if is_pythagorean "$a" "$b" "$c"; then
        echo "$a:$b:$c is pythagorean"
    else
        echo "$a:$b:$c is not pythagorean"
    fi
done < triangle.dat

Feltéve, hogy az is_pythagorean egy olyan parancs, amely megállapítja, hogy a három oldal kielégíti-e a Pitagorasz-egyenletet, a kimenet ez lenne:

3:4:5 is pythagorean
9:12:14 is not pythagorean
Állítások

Sok programozási nyelvben létezik az állításnak egy olyan formája, ahol kivétel keletkezik, ha egy feltétel nem teljesül

assert(user == "Administrator", "wrong user");

Ezt a funkciót a Bashben egy VAGY operátorral szimulálhatjuk:

die () { # a little convenience function
    echo "$*" >&2
    exit 1
}

[[ $user == "Administrator" ]] || die "wrong user"
[[ $password == "secret!" ]]   || die "incorrect password"

Stílusbeli szempontok

A hosszú parancslisták meglehetősen gyorsan olvashatatlanná válnak. A sortörések bő használata sokat segíthet.

Vegyük ezt a példát, ahol egy szót adunk egy tömbhöz, ha két feltétel teljesül.

[[ "$word" != "$topic" ]] && [[ "$key" == "$(sorted "$topic")" ]] && anagrams+=("$candidate")

A Bashben sortörést szúrhatsz be egy cső vagy egy logikai operátor után.

[[ "$word" != "$topic" ]] &&
[[ "$key" == "$(sorted "$topic")" ]] &&
anagrams+=("$candidate")

Az operátor azonban a sor végén könnyen elkerülheti a figyelmedet. Ha sorfolytatást használsz, az operátort a sor elejére teheted, így nyilvánvalóbb lesz, hogy a lista folytatódik:

[[ "$word" != "$topic" ]] \
&& [[ "$key" == "$(sorted "$topic")" ]] \
&& anagrams+=("$candidate")
Note

A sorfolytatás a „backslash” és a „sortörés” kétkarakteres sorozata (\ + \n). Amikor a Bash meglátja ezt a sorozatot, egyszerűen eltávolítja a kódból, és ezzel az aktuális sort a következő sorral folytatja. Ügyelj rá, hogy a backslash és a sortörés között ne legyen szóköz.

Íme egy másik példa

printf "%s\n" "${numbers[@]}" | bc --mathlib | sort --general-numeric-sort

vagy

printf "%s\n" "${numbers[@]}" \
| bc --mathlib \
| sort --general-numeric-sort
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg