Parancsok csoportosítása

Kicsit zavarban vagyok, mit csinálnak ezek az operátorok másképp, amikor használt bash-ban (zárójelben, dupla zárójelben, zárójelben és dupla zárójelben).

[[ , [ , ( , (( 

Láttam, hogy az emberek használják őket, ha ilyen állítások vannak:

if [[condition]] if [condition] if ((condition)) if (condition) 

Megjegyzések

Válasz

Bourne-szerű héjakban egy if utasítás általában úgy néz ki, mint

if command-list1 then command-list2 else command-list3 fi 

A then záradék akkor kerül végrehajtásra, ha a parancsok listája nulla. Ha a kilépési kód nem nulla, akkor a else záradék végrehajtásra kerül. A command-list1 lehet egyszerű vagy összetett. Ez lehet például egy vagy több csővezeték sorozata, amelyet az ;, &, &&, || vagy újsor. Az alább látható if feltételek csak a command-list1 speciális esetei:

  1. if [ condition ]

    [ a hagyományos test parancs másik neve. A [ / test egy szabványos POSIX segédprogram. Minden POSIX héj beépített (bár ezt a POSIX² nem igényli). Az test parancs beállít egy kilépési kódot és az if utasítást A tipikus tesztek az, hogy létezik-e fájl, vagy az egyik szám egyenlő-e a másikkal.

  2. if [[ condition ]]

    Ez egy új, továbbfejlesztett változat a test ¹ verzióhoz a ksh tól, amely bash , zsh , yash , busybox sh is támogatja. Ez a [[ ... ]] konstrukció egy kilépési kódot is beállít, és az if utasítás ennek megfelelően jár el. Kiterjesztett szolgáltatásai között tesztelheti, hogy egy karakterlánc megfelel-e egy helyettesítő mintának (nem a busybox sh ban).

  3. if ((condition))

    Egy másik ksh kiterjesztés, amelyet a bash és a zsh is támogat. Az aritmetika eredményeként beállítunk egy kilépési kódot, és az if utasítás megfelel rothadóan. Ha az aritmetikai számítás eredménye nem nulla, akkor egy nulla (igaz) kilépési kódot ad vissza. A [[...]] -hez hasonlóan ez az űrlap sem POSIX és ezért nem hordozható.

  4. if (command)

    Ez egy alhéjban futtatja a parancsot. Amikor a parancs befejeződik, beállít egy kilépési kódot, és az if utasítás ennek megfelelően működik.

    Az ilyen alhéj használatának tipikus oka az, hogy korlátozza a command ha command változó hozzárendelésre vagy egyéb változásra van szükség a shell környezetében. Ezek a változások nem maradnak meg az alhéj befejezése után.

  5. if command

    parancs végrehajtásra kerül, és az if utasítás működik a kilépési kódja szerint.


¹ bár nem igazán parancs, hanem egy speciális shell konstrukció, amelynek saját szintaxisa van a normál parancs szintaxisától, és jelentősen változik a shell implementációk között

² A POSIX megköveteli, hogy legyen önálló test és [ segédprogramok azonban a rendszeren, bár a [ esetén számos Linux disztribúció ismert, hogy m használja.

Megjegyzések

  • Köszönjük, hogy felvette az 5. lehetőséget. Ez a ‘ kulcs ahhoz, hogy megértsük, hogyan működik ez, és meglepően nem használják ki.
  • Ne feledje, hogy a [ valójában egy bináris, nem pedig belső parancs vagy szimbólum. Általában /bin -ban él.
  • @JulienR. valójában a [ beépített, mint az test. Kompatibilitási okokból bináris verziók érhetők el. Nézze meg a help [ és a help test.
  • Érdemes megjegyezni, hogy míg ((nem POSIX, $(( azaz a számtani kiterjesztés ‘ könnyen összetéveszthető. Gyakran megoldást jelent a [ $((2+2)) -eq 4 ] az aritmetika felhasználása a feltételes állításokban
  • bárcsak többször is fel tudnám szavazni ezt a választ. Tökéletes magyarázat.

Válasz

  • (…) zárójelben egy alhéj . Ami bennük van, az nem olyan kifejezés, mint sok más nyelvben. Ez a parancsok listája (csakúgy, mint a külső zárójelben). Ezeket a parancsokat külön alfolyamatban hajtják végre, így a zárójelben végrehajtott bármilyen átirányítás, hozzárendelés stb. Nincs hatással a zárójelen kívülre.
    • Vezetővel dollárjel, $(…) egy parancs helyettesítése : a zárójelben van egy parancs, és a parancs kimenete a parancssor részeként használják (extra kibővítések után, kivéve, ha a helyettesítés kettős idézőjelek között van, de ez “s egy másik történet ).
  • { … } zárójelek olyanok, mint a zárójelek, mivel csoportosítják a parancsokat, de csak az elemzést befolyásolják, a csoportosítást nem. A x=2; { x=4; }; echo $x program 4-et nyomtat, míg az x=2; (x=4); echo $x 2-et. (A kulcsszavak nak a zárójeleket is le kell határolni, és a parancs pozíciójában található (innen a szóköz { és a ; után } előtt található) zárójelben nincs “t”. Ez csak egy szintaxis furcsa.)
    • Vezető dollárjel esetén a ${VAR} egy paraméterbővítés , kibővül egy változó értékére, lehetséges extra transzformációkkal. A ksh93 héj a ${ cmd;} parancsot is olyan parancscsere formaként támogatja, amely nem hoz létre alhéjat.
  • ((…)) kettős zárójel vesz körül egy számtani utasítást , vagyis az egész számokat kiszámítja, más programozási nyelvekhez hasonló szintaxis. Ezt a szintaxist többnyire hozzárendelésekhez és feltételekhez használják. Ez csak a ksh / bash / zsh fájlban létezik, a sima sh-ben nem.
    • Ugyanezt a szintaxist használják az aritmetikai kifejezésekben is $((…)), amelyek kibővülnek a kifejezés egész értékéig.
  • [ … ] zárójelek veszik körül feltételes kifejezések . A feltételes kifejezések többnyire operátorokra épülnek, például a -n "$variable" tesztelheti, hogy egy változó üres-e, és -e "$file" annak ellenőrzésére, hogy létezik-e fájl. Vegye figyelembe, hogy mindegyik körül szóközre van szükség operátor (pl. [ "$x" = "$y" ], nem [ "$x"="$y" ] ), és szóköz vagy karakter, például ; mind a zárójelben, mind azon kívül (pl. [ -n "$foo" ], nem [-n "$foo"] ).
  • [[ … ]] a dupla zárójel a feltételes kifejezések alternatív formája a ksh / bash / zsh fájlban, néhány további funkcióval, például írhat [[ -L $file && -f $file ]] annak tesztelésére, hogy egy fájl szimbolikus hivatkozás-e egy szokásos fájlra, míg az egyes zárójelek [ -L "$file" ] && [ -f "$file" ] -et igényelnek. Lásd: Miért működik az idézőjel nélküli szóköz nélküli paraméterbővítés dupla zárójelben [[de nem egy zárójelben [? ] további információk erről a témáról.

A héjban a minden parancs feltételes parancs: minden parancsnak visszatérési állapota van, amely vagy 0 jelzi a sikert, vagy egy egész szám 1 és 255 között (és egyes héjakban potenciálisan több is) kudarc. A [ … ] parancs (vagy [[ … ]] szintaxis forma) egy adott parancs, amelyet szintén be lehet írni: test … és akkor sikeres, ha létezik fájl, vagy ha egy karakterlánc nem üres, vagy ha egy szám kisebb, mint egy másik, stb. A ((…)) szintaxis űrlap sikeres, ha egy szám nem nulla .Íme néhány példa a shell parancsfájl feltételfeltételeiről:

  • Tesztelje, hogy a myfile tartalmazza-e a hello:

    if grep -q hello myfile; then … 
  • Ha mydir könyvtár, váltson és csináld a következőket:

    if cd mydir; then echo "Creating mydir/myfile" echo "some content" >myfile else echo >&2 "Fatal error. This script requires mydir to exist." fi 
  • Tesztelje, van-e myfile nevű fájl az aktuális könyvtárban:

    if [ -e myfile ]; then … 
  • Ugyanaz, de lógó szimbolikus linkeket is tartalmaz:

    if [ -e myfile ] || [ -L myfile ]; then … 
  • Tesztelje, hogy a x értéke (amelyet numerikusnak feltételezünk) legalább 2, hordozhatóan:

    if [ "$x" -ge 2 ]; then … 
  • Ellenőrizze, hogy az x értéke (amely numerikusnak van feltételezve) legalább 2, a bash / ksh / zsh fájlban:

    if ((x >= 2)); then … 

Megjegyzések

  • Ne feledje, hogy az egyes zárójelek a -a -t támogatják a &&, így írhatunk: [ -L $file -a -f $file ], amely ugyanannyi karakter a zárójelben, az extra [ és ]
  • @AlexisWilke A -a és a -o operátorok problémás, mert hibás elemzéshez vezethetnek, ha az érintett operandusok egy része operátornak tűnik. Ezért ‘ ezért nem említem őket: nulla előnyük van, és don ‘ t mindig működnek. És soha ne írj nem idézett változóbővítést jó ok nélkül: [[ -L $file -a -f $file ]] rendben van, de egyes zárójelekkel [ -L "$file" -a -f "$file" ] -re van szükség (ami rendben van, pl. Ha $file mindig a következővel kezdődik: / vagy ./).
  • Vegye figyelembe, hogy ez ‘ s [[ -L $file && -f $file ]] (nem -a a [[...]] változat).

Válasz

[ vs [[

Ez a válasz a [ vs [[ a kérdés részhalmaza.

Néhány különbség a Bash 4.3.11-ben:

  • POSIX vs Bash kiterjesztés:

  • rendes parancs vs mágia

    • [ csak egy furcsa névvel ellátott rendes parancs.

      ] csak a [ utolsó argumentuma.

    Az Ubuntu 16.04 tulajdonképpen rendelkezik egy futtatható fájllal a /usr/bin/[ oldalon a coreutils , de a bash beépített verziója elsőbbséget élvez.

    Semmi sem változik úgy, ahogyan Bash elemzi a parancsot.

    Különösen a < átirányítás, && és || több parancs összefűzése, ( ) generál alhéjak, hacsak nem kerüli el a \, és a szó kibővítése a szokásos módon történik.

    • [[ X ]] egyetlen olyan konstrukció, amely miatt a X varázslatosan elemezhető. <, &&, || és () speciálisan kezelik, és a szófelosztási szabályok eltérőek.

      Vannak további különbségek is, például = és =~ .

    bash nyelven: [ egy beépített parancs, és [[ egy kulcsszó: https://askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

  • iv && és ||

    • [[ a = a && b = b ]]: igaz, logikus és
    • [ a = a && b = b ]: szintaxis hiba, && AND parancs elválasztóként értelmezve cmd1 && cmd2
    • [ a = a ] && [ b = b ]: POSIX megbízható megfelelője
    • [ a = a -a b = b ]: majdnem egyenértékű, de a POSIX elavult, mert őrült és meghiúsul a a vagy b egyes értékeknél, például ! vagy ( amelyet logikai műveletekként értelmeznének
  • (

    • [[ (a = a || a = b) && a = b ]]: hamis. A ( ) nélkül igaz lenne, mert [[ && ]] nagyobb elsőbbséggel rendelkezik, mint a [[ || ]]
    • [ ( a = a ) ]: szintaxis hiba, () alhéjként értelmezve
    • [ \( a = a -o a = b \) -a a = b ]: egyenértékű, de (), -a és -o elavult POSIX. A \( \) nélkül igaz lenne, mert a -a -nek nagyobb az elsőbbsége, mint a -o
    • { [ a = a ] || [ a = b ]; } && [ a = b ] nem elavult POSIX-megfelelője. Ebben a konkrét esetben azonban írhattunk volna csak: [ a = a ] || [ a = b ] && [ a = b ], mert a || és && a shell operátorok azonos prioritással rendelkeznek, ellentétben a [[ || ]] és [[ && ]] és -o, -a és [
  • szófelosztás és fájlnév-generálás kibővítéskor (split + glob )

    • x="a b"; [[ $x = "a b" ]]: igaz, idézőjelek nem szükségesek
    • x="a b"; [ $x = "a b" ]: szintaxis hiba, kibővül [ a b = "a b" ]
    • x="*"; [ $x = "a b" ]: szintaktikai hiba, ha az aktuális könyvtárban egynél több fájl van .
    • x="a b"; [ "$x" = "a b" ]: POSIX megfelelője
  • =

    • [[ ab = a? ]]: igaz, mert minta egyezik ( * ? [ varázslat). Nem terjed ki f-re iles az aktuális könyvtárban.
    • [ ab = a? ]: a? glob kibővül. Tehát az aktuális könyvtárban található fájloktól függően igaz vagy hamis lehet.
    • [ ab = a\? ]: hamis, nem globális kiterjesztés
    • = és == megegyezik mind a [, mind a [[, de a == egy Bash kiterjesztés.
    • case ab in (a?) echo match; esac: POSIX megfelelője
    • [[ ab =~ "ab?" ]]: hamis, elveszíti a varázslatot a "" vel a Bash 3.2 és újabb verziókban, és ha a bash 3.1 kompatibilitás nem engedélyezett (mint például a BASH_COMPAT=3.1)
    • [[ ab? =~ "ab?" ]]: igaz
  • =~

    • [[ ab =~ ab? ]]: true, POSIX kiterjesztett szabályos kifejezés egyezés, ? nem bővül globálisan
    • [ a =~ a ]: szintaktikai hiba. Nincs bash megfelelője.
    • printf "ab\n" | grep -Eq "ab?": POSIX egyenértékű (csak egysoros adatok)
    • awk "BEGIN{exit !(ARGV[1] ~ ARGV[2])}" ab "ab?": POSIX megfelelője.

Javaslat: mindig használja a []

Minden látott [[ ]] konstrukcióhoz vannak POSIX-ekvivalensek.

Ha a [[ ]] fájlt használja, akkor:

  • elveszíti a hordozhatóságot
  • kényszerítse az olvasót, hogy megtanulja egy másik bash kiterjesztés fortélyait. A [ csak egy rendes parancs furcsa névvel, külön szemantikával nem jár.

A Stéphane Chazelas a fontos javításokért és kiegészítésekért.

Megjegyzések

  • @St é phaneChazelas köszönöm az információt! Én ‘ hozzáadtam a válaszhoz a expr -t. A ” Bash ex A feszültség ” nem azt jelenti, hogy Bash volt az első héj, amely hozzáadott némi szintaxist, a POSIX sh vs Bash megtanulása már elég ahhoz, hogy megőrjítsen.
  • Lásd man test ha megpróbáltad man [ és elveszett. Ez megmagyarázza a POSIX variánst.
  • Javítás: ] a [ parancs argumentuma, de nem ‘ ne akadályozza meg a további érvek használatát. A ] -nek
    utolsó argumentumnak kell lennie [ -ig, de előfordulhat a tesztkifejezés részeként is. Például a if [ "$foo" = ] ]; then teszteli, hogy a foo változó értéke “] ” (mint if [ ] = "$foo" ]; then).

  • Köszönöm, @GordonDavisson, ‘ nem tudom ezt, javítva.
  • @ tgm1024 – Monica rosszul bánt, ez szintén érvényes szempont.

Válasz

A bash dokumentációból :

A (list) lista alhéj környezetben kerül végrehajtásra (lásd alább a PARANCS VÉGREHAJTÁS KÖRNYEZETÉT). A shell környezetét befolyásoló változó hozzárendelések és beépített parancsok a parancs befejezése után sem maradnak érvényben. A visszatérési állapot a lista kilépési állapota.

Más szavakkal, meg kell győződnie arról, hogy bármi is történik a „listában” (például egy cd), annak nincs hatása a ( és ). Az egyetlen dolog, amelyik kiszivárog, az az utolsó parancs kilépési kódja, vagy set -e az első hibát generáló parancs (más mint néhány, például if, while stb.)

((expression)) A kifejezést az alábbiakban az ARITMETIKAI ÉRTÉKELÉS alatt leírt szabályok szerint értékeljük. Ha a kifejezés értéke nem nulla, akkor a visszatérési állapot 0; különben a visszatérési állapot értéke 1. Ez pontosan megfelel a ” kifejezés ” kifejezésnek.

Ez egy bash kiterjesztés, amely lehetővé teszi matematika készítését. Ez némileg hasonlít a expr használatához a expr minden korlátozása nélkül (például ha mindenhol szóköz van, elkerülhető a * stb.)

[[ expression ]] 0 vagy 1 állapotot ad vissza, a a feltételes kifejezés kifejezésének értékelése. A kifejezések az alábbiakban a FELTÉTELES KIFEJEZÉSEK alatt ismertetett primerekből állnak. A [[és]] közötti szavakra nem történik szófelosztás és útvonalnagyság; A tilde kiterjesztése, a paraméterek és a változó kiterjesztése, az aritmetikai kiterjesztés, a parancsok helyettesítése, a folyamat helyettesítése és az idézetek eltávolítása történik. A feltételes operátorokat, mint például az -f, nem szabad megadni, hogy felismerhetők legyenek elsődlegesek.

A [[használatával a < és > operátorok lexikografikusan rendezik az aktuális területi beállításokat. = “ad58fece9c”>

ajánlatok, de erősebbek.

[ expr ] 0 (igaz) vagy 1 (hamis) a feltételes kifejezés kiértékelésétől függően. Minden operátornak és operátornak külön argumentumnak kell lennie. A kifejezések a FELTÉTELES KIFEJEZÉSEK alatt a fent leírt primerekből állnak. A test nem fogad el semmilyen beállítást, és nem fogadja el, illetve nem veszi figyelembe a – argumentumot sem, amely az opciók végét jelzi.

[…]

Ez hívja az test -t. Valójában a régi időkben a [ szimbolikus link volt az test linkre. Ugyanúgy működik, és ugyanazok a korlátai vannak. Mivel egy bináris ismeri a nevet, amellyel elindították, a tesztprogram [ néven tudja tudni, hogy mikor indult, és figyelmen kívül hagyhatja az utolsó paraméterét, amely várhatóan ]. Fun Unix trükkök.

Ne feledje, hogy bash esetén [ és test beépített funkciók (amint azt egy megjegyzés említi), mégis nagyjából ugyanazok a korlátozások érvényesek.

Megjegyzések

  • Bár test és [ természetesen beépített parancsok a Bash-ban, de valószínűleg ‘ valószínűleg külső bináris is létezik.
  • A [ külső binárisja nem szimbolikus link a test -hez a legtöbb modern rendszerben .
  • Valahogy mulatságosnak találom, hogy két külön bináris fájlt hoznak létre, amelyek mindkettőnek pontosan megvan, amire szükségük van, ahelyett, hogy csak kombinálnák őket és adnának pár feltételeset. Bár valójában a strings /usr/bin/test azt mutatja, hogy a súgószövege is benne van, ezért nem tudom, hogy mit mondjak ‘.
  • @ Random832 Értelmezem a GNU logikáját a váratlan arg0 viselkedés elkerülése érdekében, de a POSIX követelményekről, nem lennék ennyire igenlő. Míg a test parancsnak nyilvánvalóan önálló fájl alapú parancsként kell léteznie a szabvány szerint, semmi benne nem mondja ki, hogy [ változatát is így kell megvalósítani. Például a Solaris 11 nem biztosít ‘ semmilyen [ futtatható fájlt, de ennek ellenére teljes mértékben megfelel a POSIX szabványoknak
  • (az 1. kilépés) a zárójeleken kívüli hatással bír.

Válasz

Néhány példa:

Hagyományos teszt:

foo="some thing" # check if value of foo is not empty if [ -n "$foo" ] ; then... if test -n "$foo" ; then... 

test és a [ parancsok, mint minden más, ezért a változó szavakra van felosztva, hacsak nem idézőjelekben szerepelnek.

Új stílusú teszt

[[ ... ]] egy (újabb) speciális héjszerkezet, amely egy kicsit másképp működik, a legkézenfekvőbb az, hogy nem “t-split-változók:

if [[ -n $foo ]] ; then... 

Néhány dokumentáció a [ és [[ itt .

Számtani teszt:

foo=12 bar=3 if (( $foo + $bar == 15 )) ; then ... 

“Normál “parancsok:

A fentiek mindegyike úgy működik, mint a normál parancsok, és if bármilyen parancsot felvehet:

# grep returns true if it finds something if grep pattern file ; then ... 

Több parancs:

agy több parancsot is használhatunk. A parancsok halmazának ( ... ) beillesztése alhéjban futtatja őket, létrehozva a shell állapotának (munkakönyvtár, változók) ideiglenes másolatát. Ha szükségünk van rá valamely program ideiglenes futtatása egy másik könyvtárban:

# this will move to $somedir only for the duration of the subshell if ( cd $somedir ; some_test ) ; then ... # while here, the rest of the script will see the new working # directory, even after the test if cd $somedir ; some_test ; then ... 

Válasz

Parancsok csoportosítása

A Bash kétféle módon csoportosíthatja az egységként végrehajtandó parancsok listáját.

( list ) A parancsok listájának zárójelek közé helyezése alhéjkörnyezet létrehozását eredményezi, és a listában szereplő összes parancs végrehajtása abban az alhéjban történik. alhéjban végrehajtva a változó hozzárendelések nem maradnak érvényben az alhéj befejezése után.

$ a=1; (a=2; echo "inside: a=$a"); echo "outside: a=$a" inside: a=2 outside: a=1 

{ list; } a göndör zárójelek közötti parancsok listája a lista végrehajtását az aktuális shell környezetben hajtja végre . Nincs létrehozva alhéj. A pontosvessző (vagy új sor) következő lista kötelező. Forrás

${} Parameter expansion Ex: ANIMAL=duck; echo One $ANIMAL, two ${ANIMAL}s $() Command substitution Ex: result=$(COMMAND) $(()) Arithmetic expansion Ex: var=$(( 20 + 5 )) 

Feltételes konstrukciók

Egységes konzol ie []
Összehasonlításhoz ==, !=, <, és > és ezeket fel kell használni, és numerikus összehasonlítás céljából eq, ne,lt és gt kell használni.

Továbbfejlesztett zárójelek ie [[]]

A fenti példákban csak egy zárójeles zárójelet használtunk a feltételes kifejezés becsatolásához, de a bash kettős zárójelet tesz lehetővé, amely az egy zárójeles szintaktika továbbfejlesztett változataként szolgál.

Összehasonlításként a ==, !=, <, és a > szó szerint használható.

  • [ a teszt parancs szinonimája. Még akkor is, ha a héjba van építve, új folyamatot hoz létre.
  • [[ a továbbfejlesztett változata, amely kulcsszó, nem program .
  • [[ Korn és Bash. / li>

Forrás

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük