Kurzusok
/
Bash
Bash
/
Tanterv
/
Az idézőjelek fontossága
Az

Az idézőjelek fontossága ebben a kurzusban: Bash

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

A(z) Az idézőjelek fontossága fogalomról

Egy tanácsot a kezdő bash-programozók újra és újra hallani fognak:

Tedd idézőjelbe a változóidat!

Miért is?

Amikor kifejtesz egy változót (például $name), szinte mindig a változó értékét szeretnéd egyetlen stringként (vagy számként) használni. Nem szeretnéd, hogy az érték váratlanul két vagy több külön stringként legyen kezelve.

Idézőjelek

Az idézőjelek jelentik az elsődleges mechanizmust arra, hogy egy szövegrész egyetlen szóként legyen kezelve. Két fő fajtájuk van.

Kettős idézőjelek

A kettős idézőjelek lehetővé teszik a paraméterkifejtést, az aritmetikai kifejtést és a parancshelyettesítést.

echo "This is bash version $BASH_VERSION"

Egy literál kettős idézőjelet úgy tehetsz a kettős idézőjelek közé zárt stringbe, hogy egy backslash-t teszel elé.

echo "She said \"Let me teach you about bash.\""

Egyszeres idézőjelek

Az egyszeres idézőjelek nem engedélyeznek semmilyen kifejtést.

echo 'This is bash version $BASH_VERSION'
# ...^..................................^
# prints exactly: This is bash version $BASH_VERSION

Egy egyszeres idézőjelet nem lehet beágyazni az egyszeres idézőjelek közé zárt stringbe.

Miért fontos az idézőjelek használata?

Mi is a baj pontosan az echo $name paranccsal?

Amikor a shell feldolgoz egy kódsort, sorrendben többféle kifejtést végez. Az utolsó kifejtések közül kettő a szófelbontás és a fájlnévkifejtés.

Szófelbontás

A paraméterkifejtés, a parancshelyettesítés vagy az aritmetikai kifejtés minden olyan eredménye, amely nem kettős idézőjelek között jött létre, részt vesz a „szófelbontásban”. A shell fogja a kifejtett eredményt, és minden olyan karaktersorozatnál szétvágja, amely szerepel a $IFS értékében. Alapértelmezés szerint ez a szóköz, a tabulátor és az újsor.

Ezt egy shell-ciklussal is láthatjuk működés közben:

sentence="The quick brown fox jumps."
i=0
for word in "$sentence"; do echo "$((++i)) $word"; done
# ..........^.........^

kimenete:

1 The quick brown fox jumps.

De idézőjel nélkül:

i=0
for word in $sentence; do echo "$((++i)) $word"; done
# .........^.........^

kimenete:

1 The
2 quick
3 brown
4 fox
5 jumps.

Nézzük meg egy másik $IFS-értékkel:

csv="first,second,third"
IFS=","
for word in $csv; do echo "$word"; done

kimenete:

first
second
third
A szófelbontás kikapcsolása

A szófelbontás kikapcsolásának egyik technikája, ha a $IFS-t üres stringre állítod

sentence="The quick brown fox jumps."
IFS=    # or explicitly, IFS=""
i=0
for word in $sentence; do echo "$((++i)) $word"; done
# .........^.........^

kimenete:

1 The quick brown fox jumps.

A változók idézőjel nélkül hagyása azonban nem ajánlott, hacsak nem kapcsolod ki a fájlnévkifejtést is. Hogy ezt hogyan teheted meg, azt alább meglátjuk.

Fájlnévkifejtés

A „glob” minták segítségével tömören kifejezhetsz egy fájlhalmazra illeszkedő mintát. Például egy könyvtár összes Markdown-fájlját a *.md mintával illesztheted. A glob-minták a Unix feltalálása óta léteznek.

A glob helyettesítő karakterei:

  • A * nulla vagy több tetszőleges karakterre illeszkedik,

  • A ? pontosan egy tetszőleges karakterre illeszkedik,

  • A [...] pontosan egy karakterre illeszkedik a zárójelek között felsorolt karakterek halmazából.

    Advanced
    Rengeteg részlet van a karakterhalmazokról. Kattints ide a megjelenítésükhöz.
    • A [abc] pontosan egy olyan karakterre illeszkedik, amely a, b vagy c.
      • hogy egy literál csukó zárójelet is bevonj a kifejezésbe, tedd a nyitó zárójel utáni első karakterré (az opcionális ^ után)
        • A [][] egy karakterhalmaz, amely vagy egy csukó, vagy egy nyitó zárójelre illeszkedik.
        • vagy escape-eld backslash segítségével: [[\]]
    • A [x-y] pontosan egy olyan karakterre illeszkedik, amely a x és y közötti tartományba esik
      • ahhoz, hogy egy literál kötőjelet is bevonj egy karakterhalmazba, annak vagy a nyitó zárójel utáni első karakternek kell lennie (az opcionális ^ után), vagy a csukó zárójel előtti utolsó karakternek.
        • A [-xy] és a [xy-] is pontosan egy olyan karakterre illeszkedik, amely -, x vagy y
        • vagy escape-eld backslash segítségével: [x\-y]
      • több tartomány is megadható, például a [0-9A-Fa-f] egy hexadecimális számjegyre illeszkedik
    • A [^abc] pontosan egy olyan karakterre illeszkedik, amely NEM a, b vagy c,
    • A [^x-y] pontosan egy olyan karakterre illeszkedik, amely NEM esik a x és y közötti tartományba
    • A [[:character_class:]] egy olyan karakterre illeszkedik, amely a megnevezett „character_class”-ba tartozik
      • a rendelkezésre álló karakterosztályok:
        • lower -- kisbetűk
        • upper -- nagybetűk
        • alpha -- betűk
        • digit -- számjegyek
        • alnum -- betűk és számjegyek
        • space -- whitespace
        • blank -- vízszintes whitespace (szóköz és tabulátor)
        • xdigit -- hexadecimális számjegyek
        • word -- azonosítóban engedélyezett karakterek (betűk, számok, alulvonás)
        • punct -- írásjelek
        • cntrl -- vezérlőkarakterek
        • graph -- „látható” karakterek
        • print -- látható karakterek és a szóköz
      • ezek kombinálhatók:
        • a [[:alpha:]] osztály a [[:lower:][:upper:]] osztályokból áll
        • a [[:alnum:]] osztály a [[:alpha:][:digit:]] osztályokból áll
        • a [[:word:]] osztály a [[:alnum:]_] osztályból áll
        • az alulvonás (oktális 137) egyszerre része a [[:word:]] és a [[:punct:]] osztálynak
        • a [[:graph:]] osztály a [[:alnum:][:punct:]] osztályokból áll
        • a [[:print:]] osztály a [[:graph:] ] osztályból áll -- csak a szóközből (oktális 040), semmilyen más whitespace-ből nem.
Fájllista bejárása

Egy fájllistán végigmehetsz egy for ciklussal

for file in *.csv; do
    do_something_with "$file"
done

Figyeld meg, hogy a "$file" változó idézőjelben van. A glob minta olyan fájlokat is visszaadhat, amelyek nevében szóköz van. Idézőjelbe kell tennünk a változót, hogy a do_something_with parancs pontosan egy argumentumot kapjon: a fájlnevet.

A glob minták nem reguláris kifejezések

A glob minták nem reguláris kifejezések.

  • pontosan egy karakterre illeszkedik
    • regex .
    • glob ?
  • nulla vagy több karakterre illeszkedik
    • regex .*
    • glob *
      • a .* glob minta azt jelenti: „olyan fájlnévre illeszkedik, amelynek első karaktere egy literál pont, amelyet nulla vagy több tetszőleges karakter követ”.
  • egy vagy több karakterre illeszkedik
    • regex .+
    • glob ?*
  • a regex és a glob karakterhalmazai ugyanúgy viselkednek.
Advanced

A Bash kiterjesztett mintákat kínál, amelyek közelebb állnak a reguláris kifejezésekhez.

Idézőjelek és fájlnévkifejtés

Vannak helyzetek, amikor el szeretnéd nyomni a fájlnévkifejtést. A felhasználói bemenet kezelése egy ilyen eset. Vegyük ezt a kódrészletet

read -p "Enter something: " user_input
echo $user_input

Ha a felhasználó beír egy csillagot (*), mi lesz a kimenet? Az aktuális könyvtárban lévő fájlok listája. Valószínűleg nem ezt szeretnéd.

Egy másik példa, amikor mintákat adunk argumentumként olyan programoknak, amelyek mintákat várnak. A tr programot gyakran használjuk szövegmanipulációra. Egy változó értékének kisbetűsítéséhez ezt teheted

var="My Puppet"
echo "$var" | tr '[:upper:]' '[:lower:]'

kimenete:

my puppet

Gyakori hiba, hogy elfelejtjük idézőjelbe tenni a tr argumentumait: tr [:upper:] [:lower:]

Caution

Miért jelent ez problémát? Az idézőjel nélküli glob minták arra a fájllistára lesznek kifejtve, amelyek illeszkednek. Tegyük fel, hogy a szkriptedet használónak vannak p, u és w nevű fájljai az aktuális könyvtárban:

touch p u w
var="My Puppet"
echo "$var" | tr [:upper:] [:lower:]

Ez hibát eredményez!

Az idézőjel nélküli [:upper:] minta a :, u, p, e vagy r bármelyikére illeszkedik. Az idézőjel nélküli [:lower:] minta a :, l, o, w, e vagy r bármelyikére illeszkedik. A Bash az első mintához a p és u fájlt párosítja, a második mintához a w fájlt, és a tr így hívódik meg:

echo "$var" | tr p u w

És ez rossz számú argumentum a tr számára.

A fájlnévkifejtés kikapcsolása

A set paranccsal kapcsolhatod ki a fájlnévkifejtést.

echo *      # prints a list of files
set -f      # disable filename expansion
echo *      # prints a literal asterisk
set +f      # enable filename expansion
A fájlnévkifejtés szabályozása

A beépített shopt parancsnak több beállítása is szabályozza, hogyan működik a fájlnévkifejtés. Néhány érdekes közülük:

  • shopt -s nocaseglob -- kis- és nagybetűt nem megkülönböztető illesztés
  • shopt -s extglob -- kiterjesztett minták engedélyezése
  • shopt -s nullglob -- ha egyetlen fájl sem illeszkedik, a mintát semmire cseréli. Az alapértelmezett viselkedés, hogy a minta a helyén marad literál stringként.
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg