Bash dacă comparație de șiruri. Comparație de șiruri fără majuscule și minuscule în Bash. Lista operatorilor logici care sunt utilizați pentru constructul if-then-else-fi

Acest subiect este al patrulea subiect din seria „Bash Shell Language”. El va vorbi despre astfel de structuri de control ale limbajului ca declarații condiționate. Dar înainte de a trece la descrierea lor, este necesar să ne oprim asupra unor nuanțe care vor face mai ușor de înțeles luarea în considerare a materialului de mai jos.
Mai întâi, să vedem ce este o listă de comenzi. O listă de comenzi este o singură comandă, conductă sau secvență de comenzi/conducte separate de unul dintre următorii operatori: „;”, „&&”, „||”, terminat cu punct și virgulă.
; - operator de executare secvențială a mai multor comenzi. Fiecare comandă ulterioară începe să fie executată numai după finalizarea celei anterioare (nu contează dacă a avut succes sau nu);
&& - operatorul pentru a executa o comandă numai după ce cea anterioară a fost finalizată cu succes;
|| - operatorul de executare a unei comenzi numai după ce cea anterioară a fost executată incorect.
Codul de succes este 0, iar codul de eroare nu este zero (în funcție de tipul de eroare). Acest lucru nu trebuie confundat cu limbajele de programare convenționale, unde 1 este analog cu adevărat și 0 este analog cu fals.
Acum putem începe să luăm în considerare direct declarațiile condiționale.

operator de caz

Sintaxa generală a instrucțiunii case este:

valoarea cazului în
template1) lista1;;
template2 | template3) list2;;
esac

Secvența logică de execuție a instrucțiunii case:
a) se caută primul model care corespunde valorii;
b) dacă se găsește, se execută lista de comenzi corespunzătoare, care se termină cu „;;”;
c) controlul se transferă asupra situaţiilor în urma construirii cazului.
Șablonul și lista sunt separate prin caracterul „)”. O listă de comenzi poate corespunde mai multor condiții, apoi acestea trebuie separate prin simbolul „|”.
În șabloane puteți folosi simbolurile „*”, „?”, „”, care au fost discutate în al doilea subiect al seriei. Cu ajutorul lor, puteți implementa o instrucțiune care acționează ca implicită într-o instrucțiune switch în limbi precum C, PHP.
Iată un exemplu de utilizare a cazului:
echo -n "[Vizualizator universal] Specificați numele fișierului: "; citește cazul fișierului „$Fișier” în *.jpg|*.gif|*.png) eog $Fișier ;; *.pdf) evince $File ;; *.txt) mai puțin $Fișier ;; *.html) firefox $File ;; /dev/*) echo „Ei bine, acestea sunt fișiere înfricoșătoare.” ;; *) echo "Bine, bine - nu atât de universal." echo "Nu sunt familiarizat cu acest tip de fișier. Nu știu cum să-l vizualizez." ;; esac
Un alt exemplu de utilizare a constructului case:
echo "Eroare. Cui să trimit mesajul?" echo „Către șeful: b” echo „Către colegi: c” echo „Nimănui: orice cheie” citește răspuns caz $răspuns în b|B) mail –s „jurnal de erori” șeful< error.log;; c|C) mail –s "Help! error log" –c denis nick < error.log;; *) echo "error"; exit;; esac

Operator condiționat dacă

Sintaxa generală a instrucțiunii if este:

dacă list1 atunci
lista2

fi

Parantezele pătrate indică aici constructe opționale. Secvența logică de execuție a instrucțiunii case:
a) lista1 este executată;
b) dacă se execută fără erori, se execută list2. În caz contrar, list3 este executată, iar dacă se finalizează fără erori, list4 este executată. Dacă list3 returnează și un cod de eroare, list5 este executată;
c) controlul este transferat operatorilor urmând constructul if.
Iată un exemplu de utilizare dacă:
if grep -q Fișier Bash, atunci echo „Fișierul conține cel puțin un cuvânt Bash”. fi
Când dacă și apoi apar pe aceeași linie, constructele if și apoi trebuie să se încheie cu punct și virgulă. De exemplu:
$dacă [$? –ne 0 ]; apoi ecou „Eroare”; fi
Acum, știind că este posibil să plasați dacă și apoi pe aceeași linie, să rescriem exemplul de mai sus:
if grep -q fișier Bash; apoi echo „Fișierul conține cuvântul Bash”. fi

Declarația de test și expresiile condiționale

În exemplul de mai sus, se utilizează o verificare a stării în loc de a analiza codul de ieșire. Două forme ale acestui test sunt echivalente: comanda de testare încorporată și [condiție]. De exemplu, pentru a verifica existența unui fișier trebuie să scrieți:
test –e<файл>
sau
[ -e<файл> ]
Dacă se folosesc paranteze pătrate, acestea trebuie separate între ele printr-un spațiu, deoarece „[” este numele comenzii, iar „]” este ultimul argument necesar pentru finalizarea acesteia.
Dacă condiția este verificată cu succes, se returnează 0, iar dacă este fals, se returnează codul de eroare 1.
Comanda de testare poate verifica dacă un șir este gol. Un șir nevid are ca rezultat codul de ieșire 0. Gol, respectiv – 1. De exemplu:
$test $USER; eco $?
Designul „” este mai universal în comparație cu „”. Aceasta este o versiune extinsă a comenzii de testare. În cadrul acestui construct, nu se realizează nicio interpretare suplimentară a numelor fișierelor și argumentele nu sunt împărțite în cuvinte separate, dar este permisă înlocuirea parametrilor și a comenzilor. De exemplu:
file=/etc/passwd dacă [[ -e $fișier ]] apoi ecou „Fișierul cu parolă găsit”. fi
Construcția „” este de preferat „” deoarece va ajuta la evitarea unor erori logice. De exemplu, operatorii „&&”, „||”, „<" и ">„ în interiorul ” ” sunt perfect acceptabile, în timp ce în interiorul „ ” generează mesaje de eroare.
Construcția „(())” vă permite să evaluați expresii aritmetice din ea. Dacă rezultatul calculului este zero, este returnat un cod de eroare. Un rezultat diferit de zero al unui calcul produce un cod returnat de 0. Adică, exact opusul testului și instrucțiunilor „” discutate mai sus.
Declarația if permite verificări imbricate:
if echo „Următorul *dacă* este în primul *dacă*”.< b)) else [[ $a < $b ]] fi then echo "$a меньше $b" fi

dacă [[ $comparație = „întreg” ]] atunci ((a
! <выражение>Expresiile condiționate pot fi combinate folosind operații logice obișnuite:
<выражение1>– negare;<выражение2>-o
<выражение1>– ȘI logic;<выражение2>– o

– SAU logic.
Expresii condiționale elementare pentru fișiere:
-e - fisierul exista;
-f - un fișier obișnuit (nu un director sau un fișier de dispozitiv);
-s - dimensiunea fișierului diferită de zero;
-d - fișierul este un director;
-b - fișierul este un dispozitiv bloc (floppy, cdrom, etc.); -c - fișierul este un dispozitiv de caractere (tastatură, modem, placa de sunet
etc.);
-p - fisierul este un canal;
-h - fișierul este o legătură simbolică;
-L - fisierul este o legatura simbolica;
-S - fișierul este un socket;
-t - fișierul este asociat cu dispozitivul terminal;
-r - fișierul este lizibil (de către utilizatorul care a lansat scriptul);
-w - fișierul este inscriptibil (pentru utilizatorul care a lansat scriptul);
-x - fișierul este disponibil pentru execuție (utilizatorului care a lansat scriptul);
-g - (sgid) steag pentru fișier sau director este setat;
-u - (suid) steag pentru fișier este setat;
-k - steag sticky bit este setat;
-O - ​​sunteți proprietarul dosarului;
-G - aparțineți aceluiași grup cu fișierul;
-N - fișierul a fost modificat de la ultima citire;
fisier1 -nt fisier2 – fisier1 este mai nou decat fisier2;
fisier1 -ot fisier2 – fisier1 este mai vechi decat fisier2;

fișier1 -ef fișier2 – fișierul1 și fișierul2 sunt legături „hard” către același fișier.
Expresii condiționale elementare pentru compararea șirurilor de caractere:
-z șir – lungimea șirului este 0;
line1 == line2 – liniile se potrivesc (asemănător cu „=”);
line1 !== line2 – liniile nu se potrivesc (asemănător cu „!=”);
linia 1< строка2 – строка1 предшествует строке2 в лексикографическом порядке;
line1 > line2 – rândul1 urmează rândul2 în ordine lexicografică.
Aritmetică expresie condiționată are formatul:
argument1 operație argument2, unde argumentele sunt numere întregi și sunt permise următoarele operații:
-eq – egal;
-ne – nu este egal;
-lt – mai puțin;
-le – mai mic sau egal;
-gt – mai mult;
-ge – mai mare sau egal cu;
< - меньше (внутри двойных круглых скобок);
<= - меньше или равно (внутри двойных круглых скобок);
> - mai mare decât (între paranteze duble);
>= - mai mare sau egal cu (între paranteze duble).

Să rescriem exemplul anterior folosind o instrucțiune if:
echo "Eroare. Cui să trimit mesajul?" echo "Boss: b" echo "Colegi: c" echo "Nimeni: orice tastă" citește răspunsul if [ "$răspuns" == "b" –o "$răspuns" == "B" ]; apoi mail –s „jurnal de erori” șeful< error.log; elif [ "$answer" == "c" –o "$answer" == "C" ]; then mail –s "Help! error log" –c denis nick < error.log; else echo "error"; exit; fi

În următorul subiect voi continua să mă uit la structurile de control ale interpretului de comandă bash. Și anume, vor fi luați în considerare operatorii de buclă. Și acum aștept comentarii și critici :).

UPD: Mulțumesc utilizatorului

Când scriu scripturi în Bash, nu numai programatorii experimentați, ci și cei nou în shell-ul Bash se confruntă cu lucrul cu șiruri. Acest lucru este cel mai adesea necesar atunci când citiți comenzile introduse de utilizator ca argumente pentru un script executabil, precum și atunci când procesați fișiere text. Și una dintre tehnicile necesare în acest caz este compararea șirurilor.

Acest articol va analiza compararea șirurilor Bash, precum și câteva nuanțe privind utilizarea operațiilor de comparare și rezolvarea erorilor comune.

Aceste operații vă permit să determinați dacă șirurile comparate sunt aceleași:

  • = - egal, de exemplu dacă [ "$x" = "$y" ]
  • == - un sinonim pentru operatorul „=", de exemplu dacă [ "$x" == "$y" ]
  • != - nu sunt egale, de exemplu dacă [ "$x" != "$y" ]

#!/bin/bash
testuser=anton
dacă [ $USER = $testuser ]
apoi
echo „Bun venit $testuser”
fi

Rezultatul scenariului:

Când testați egalitatea folosind comanda test(sinonim cu paranteze pătrate) se iau în considerare toate semnele de punctuație și diferențele în cazul literelor șirurilor comparate.

Câteva caracteristici ale comparației șirurilor cu modele:

# returnează adevărat dacă șirul conținut în $x începe cu caracterul „y”
[[ $x == y* ]]
# returnează adevărat dacă șirul de la $x este egal cu exact două caractere „y*”
[[ $x == "y*" ]]
# returnează adevărat dacă $x conține numele unui fișier conținut în directorul curent care începe cu „y”
[ $x == y* ]
# returnează adevărat dacă șirul $x este egal cu două caractere „y*”.
[ "$x" == "y*" ]

De exemplu, verificând un șir bash pentru a vedea dacă începe cu caracterul y:

#!/bin/bash
x=yandex
[[ $x == y* ]]
eco $?

Rezultatul executării codului:

Scriptul iese 0 (zero) deoarece am solicitat să fie afișat codul de eroare al ultimei instrucțiuni executate. Iar codul 0 înseamnă că scriptul a fost executat fără erori. Și într-adevăr - o variabilă $x conţine şirul yandex, care începe cu caracterul „y”. În caz contrar, se poate scrie „1”. Aceasta este o modalitate destul de convenabilă de a depana scripturile.

Compararea șirurilor de caractere alfabetic în Bash

Sarcina devine mai dificilă atunci când se încearcă să se determine dacă un rând este un predecesor al altui rând într-o secvență de sortare ascendentă. Oamenii care scriu scripturi bash se confruntă adesea cu două probleme cu privire la operațiunile mai mare decât și mai puțin decât în ​​raport cu comparații. șiruri Linux, care au soluții destul de simple:

În primul rând, caracterele mai mari decât și mai mici decât trebuie să fie eliminate precedându-le cu o bară oblică inversă (\), deoarece altfel shell-ul le va trata ca caractere de redirecționare și șirurile ca nume de fișiere. Acesta este unul dintre acele cazuri în care este destul de dificil să găsiți eroarea.

#!/bin/bash
# utilizarea incorectă a operatorilor de comparare a șirurilor
val1=baseball
val2=hochei
dacă [ $val1 > $val2 ]
apoi

altfel

fi

Ce obțineți dacă comparați șirurile bash:

După cum puteți vedea, simbolul „mai mare decât” în forma sa imediată a condus la rezultate incorecte, deși nu au fost generate erori. În acest caz, acest caracter a făcut ca fluxul de ieșire să fie redirecționat, astfel încât nu au fost detectate erori de sintaxă și, ca urmare, un fișier numit hochei:

Pentru a rezolva această eroare, trebuie să evadați caracterul „>”, astfel încât condiția să arate astfel:

...
dacă [ $val1 \> $val2 ]
...

Apoi rezultatul programului va fi corect:

În al doilea rând, șirurile ordonate folosind operatorii mai mare decât și mai puțin decât sunt aranjate diferit decât cu comanda sorta. Aici, problemele sunt mai greu de recunoscut și s-ar putea să nu le întâlnești deloc dacă comparația nu ține cont de cazul literelor. În echipă sortaŞi test comparația are loc în moduri diferite:

#!/bin/bash
val1=Testare
val2=testare
dacă [ $val1 \> $val2 ]
apoi
echo „$val1 este mai mare decât $val2”
altfel
echo „$val1 este mai mic decât $val2”
fi

Rezultatul codului:

În echipă test liniile cu litere mari vor preceda mai întâi liniile cu litere mici. Dar dacă scrieți aceleași date într-un fișier, căruia îi aplicați apoi comanda sorta, apoi liniile cu litere mici vor fi primele:

Diferența dintre munca lor este că în test Pentru a determina ordinea de sortare, se ia ca bază aranjarea caracterelor din tabelul ASCII. ÎN sorta Este utilizată ordinea de sortare specificată pentru setările locale.

Verificarea unui șir pentru o valoare goală

Comparație folosind operatori -zŞi -n folosit pentru a determina dacă o variabilă conține conținut. Deci poți găsi linii goale bash. Exemplu:

#!/bin/bash
val1=testare
val2=""
# verifică dacă șirul este gol
dacă [ -n $val1 ]
apoi
echo „Șirul „$val1” nu este gol”
altfel
echo „Șirul „$val1” este gol”
fi
# verifică dacă șirul este gol
dacă [ -z $val2 ]
apoi
echo „Șirul „$val2” este gol”
altfel
echo „Șirul „$val2” nu este gol”
fi
dacă [ -z $val3 ]
apoi
echo „Șirul „$val3” este gol”
altfel
echo „Șirul „$val3” nu este gol”
fi

Rezultatul codului:

Acest exemplu creează două variabile șir - val1Şi val2. Operațiunea -n determină dacă o variabilă are val1 lungime diferită de zero și -z verificări val2Şi val3 la zero. Este de remarcat faptul că acesta din urmă nu a fost definit până în momentul comparației, dar interpretul consideră că lungimea sa este încă egală cu zero. Această nuanță ar trebui luată în considerare în timpul diferitelor verificări de script. Și, dacă nu sunteți sigur ce valoare este conținută în variabilă și dacă este setată deloc, merită să o verificați folosind operatorul -n sau -zși abia apoi să-l folosească în scopul propus.

Merită să acordați atenție funcției -n. Dacă o variabilă nedeclarată sau goală îi este transmisă pentru testare, va returna mai degrabă adevărat decât fals. Pentru astfel de cazuri, ar trebui să includeți șirul (variabila) testat între ghilimele duble, astfel încât să arate astfel:

...
dacă [ -n "$val1" ]
...

Concluzii

Există anumite nuanțe ale operațiunilor de comparare a șirurilor Bash prezentate care merită înțelese pentru a preveni erorile de script. Dar, în practică, există multe astfel de situații, așa că este imposibil să-ți amintești totul (darămite să-l descrii).

În scenarii Bash shell putem face comparații de numere. Pentru a efectua o operație de comparare a numărului în Bash, trebuie să utilizați starea „test” într-o buclă if sau. În această postare vă vom spune cum să comparați numerele în bash.

Operatori pentru compararea numerelor Bash

operatorce faceexemplu
-echivcompara numerele în bash pentru egalitate, returnează 0 dacă este egaldacă [ $a -eq $b ] atunci
-gecomparând numerele în bash dacă sunt mai mari sau egale. Rezultatul returnează 0 dacă este mai mare sau egal cudacă [ $a -ge $b ] atunci
-gtcompară numerele în bash dacă sunt mai mari.dacă [ $a -gt $b ] atunci
-leCompară numerele din bash dacă sunt mai mici sau egale.dacă [ $a -le $b ] atunci
-ltcompară numerele în bash dacă sunt mai mici.dacă [ $a -lt $b ] atunci
-necompară numerele în bash dacă nu sunt egale sau nu.dacă [ $a -ne $b ] atunci

Exemple în detaliu de operatori de comparare a numărului în Bash:

1. operator-echiv

Acest operator compară numere, va verifica dacă valoarea este egală sau nu. Dacă este egal, atunci este returnat 0.

# cat test.sh #!/bin/bash echo „introduceți valoarea variabilei” citiți un ecou „introduceți valoarea variabilei” citiți b dacă [ $a -eq $b ] apoi echo „Valoare returnată:: $ ?" echo "a și b sunt egale" else echo "Valoare returnată:: $?" echo „a și b nu sunt egali” fi #

Execuţie:

# sh test.sh introduceți valoarea variabilei 2 introduceți valoarea variabilei 3 Valoarea returnată:: 1 a și b nu sunt egale # sh test.sh introduceți valoarea variabilei 2 introduceți valoarea variabilei 2 Valoare returnată:: 0 a și b sunt egale cu #

În exemplul de mai sus, am luat pentru prima dată numerele 2 și 3, iar sistemul a returnat valoarea 1, totuși, când am luat aceleași valori pentru a și b, variabila returnează o valoare zero.

2. operator-ge

Acest operator compară numere și testează dacă valorile sunt mai mari sau egale cu. Dacă valoarea este mai mare sau egală cu, atunci valoarea returnată este 0.

# cat test1.sh #!/bin/bash #program de comparare pentru -ge echo „introduceți valoarea variabilei” citiți un echo „introduceți valoarea variabilei b” citiți b dacă [ $a -ge $b ] atunci echo "valoare returnată: : $?" echo "a este mai mare sau egal cu b" else echo "return value:: $?" echo „a nu este mai mare sau egal cu b” fi #

3. operator -gt

Acest operator de comparare a numărului va testa numărul să fie mai mare. Dacă valoarea este mai mare, atunci returnează 0.

# cat test2.sh #!/bin/bash #program de comparație pentru -gt b=100 echo „introduceți o valoare mai mare de 100” citiți a if [ $a -gt $b ] apoi echo „Foarte bine” else echo „Nu foarte bine" fi

4. operator-le

Acest operator de comparare a numărului va testa valori mai mici sau egale cu. Dacă este mai mică sau egală cu, atunci valoarea returnată este 0.

#compara program pentru -le b=5 echo "introduceți o valoare mai mică sau egală cu 5" citiți a if [ $a -le $b ] apoi echo "toate corecte" altfel echo "incorect" fi #

5. operator-lt

Acest operator de comparare a numerelor va testa valori pentru mai puțin de. Dacă numărul este mai mic, atunci valoarea returnată este 0.

Condiția if-else este aplicată în Scripturi BASH foarte des. Condiția în sine are un aspect oarecum ciudat [[ afecțiune ]]. Atenție la indentări. Fără ele, condiția nu va funcționa. Iată o listă de operatori logici pentru condiția [[ ? ]]:

Lista operatorilor logici care
folosit pentru construcția dacă-atunci-altfel-fi

#!/bin/bash dacă [[ $1 > 2 ]] atunci # dacă [[ ? ]] echo $1" este mai mare decât 2" altfel # dacă nu se potrivește cu echo $1" este mai mic de 2 sau 2" fi

Unii dintre voi poate considera ciudat operatorul de egalitate -eq. Încercați să utilizați operatori familiari >

Să presupunem că aveți un script și trebuie să verificați utilizatorul. Dacă utilizatorul nu este root, scriptul se va opri.

#!/bin/bash if [ "$(whoami)" != "rădăcină" ]; apoi echo „Nu aveți permisiunea de a rula $0”.

ieșirea 1; fi

Adesea trebuie să verificați o variabilă pentru a vedea dacă are o valoare. Dacă nu există nimic în variabilă, atunci puteți opri scriptul.

#!/bin/bash if [ -n "$num" ]; apoi „variabila are ceva și poți începe un alt proces” altfel echo „o variabilă goală, oprește scriptul” exit 0; fi

Dacă variabila este goală, atunci poate fi completată.

#!/bin/bash if [ -z "$num" ]; atunci echo "variabila este goală" num=1 else echo "num="$num fi

O variabilă goală i se poate atribui o valoare implicită. Această intrare este mai scurtă decât în ​​exemplul anterior. #!/bin/bash # Scrieți DEFAULT dacă argumentele linie de comandă

lipsește [ -z "$arg1" ] && arg1=DEFAULT echo $arg1

Compararea șirurilor în Bash nu provoacă probleme până când nu vă confruntați cu sarcina de a compara două șiruri fără a ține seama de majuscule și minuscule. Voi oferi mai multe opțiuni pentru rezolvarea problemei pe care o folosesc eu. Particularitatea acestor soluții este că folosesc numai capacitățile încorporate ale shell-ului Bash.

Pentru a începe, voi crea două variabile str1 și str2 care conțin șirurile de comparat. Acestea sunt cele care vor fi folosite în următoarele exemple de cod.

#!/bin/bash str1 = „Șir de comparat” str2 = „Șir de comparat”

Prima versiune a comparației de șiruri care nu ține seama de majuscule și minuscule pe care vreau să o propun utilizează gestionarea opțiunilor shell folosind comanda încorporată shopt.

shopt -s nocasematch [[ $str1 == $str2 ]] && echo "match" || echo "nu se potrivește" shopt -u nocasematch Următoarea versiune a comparației de șiruri care nu ține seama de majuscule și minuscule se bazează pe principiul conversiei independente a șirurilor într-un caz obișnuit. Această variantă de cod funcționează pe Bash 4 și mai târziu. Folosește-l pentru mai mult

versiunea timpurie

Bash va arunca o eroare.

Deci, pentru a compara șirurile convertite în litere mici, puteți utiliza următoarea opțiune de cod.

[[ " $( str1 ^^ ) " == " $( str2 ^^ ) " ]] && echo "potrivire" ||

ecou "nu se potrivește" Ca varianta alternativa

, conversia șirurilor de caractere într-un singur registru poate fi efectuată în momentul declarării variabilelor. Pentru a face acest lucru, utilizați comanda încorporată shell declare.

Pentru a declara o variabilă care conține text cu minuscule, utilizați următorul cod.

#!/bin/bash declare -l str = "Șir de caz Camel"

Ca urmare a executării acestui cod, variabila str va conține un șir cu litere mici, în ciuda faptului că șirul atribuit a fost scris cu majuscule camel. Puteți schimba majusculele unui șir deja specificat într-o variabilă după cum urmează.

#!/bin/bash str = "Șir de caz Camel" declare -l str str = $str echo $str

Pentru a converti un șir în majuscule, în exemplul de cod de mai sus, ar trebui să schimbați apelul la comanda declare, folosind comutatorul -u în loc de comutatorul -l.

Acum, compararea șirurilor care nu ține seama de majuscule și minuscule folosind comanda declare se poate face după cum urmează.

declare -l str1_l = $str1 declare -l str2_l = $str2 [[ $str1_l == $str2_l ]] && echo "match" ||