Windows.  Virus.  Anteckningsböcker.  Internet.  kontor.  Verktyg.  Förare

När man skriver manus i Bash ställs inte bara erfarna programmerare, utan även nykomlingar till Bash-skalet, inför att arbeta med strängar. Detta behövs oftast när man läser kommandon som användaren angett som argument till ett körbart skript, såväl som vid bearbetning textfiler. Och ett av de nödvändiga knepen i det här fallet är en strängjämförelse.

Den här artikeln kommer att titta på att jämföra Bash-strängar, såväl som några av nyanserna av att använda jämförelseoperationer och lösa vanliga fel.

Dessa operationer låter dig avgöra om de jämförda strängarna är desamma:

  • = - lika, till exempel if [ "$x" = "$y" ]
  • == - synonym för operatorn "=", till exempel if [ "$x" == "$y" ]
  • != - inte samma sak, till exempel if [ "$x" != "$y" ]

#!/bin/bash
testuser=anton
om [$USER = $testuser]
sedan
echo "Välkommen $testuser"
fi

Resultatet av manuset:

Vid kontroll av likhet med kommandot testa(synonymt med hakparenteser ) alla skiljetecken och skiftlägesskillnader i de jämförda strängarna beaktas.

Några funktioner i strängmatchning med mönster:

# returnerar sant om strängen i $x börjar med "y"
[[ $x == y* ]]
# returnerar sant om strängen för $x är exakt två tecken "y*"
[[ $x == "y*" ]]
# returnerar sant om $x innehåller namnet på en fil som finns i den aktuella katalogen som börjar med "y"
[ $x == y* ]
# returnerar sant om strängen $x är lika med två tecken "y*"
[ "$x" == "y*" ]

Kontrollera till exempel en bashsträng för att se om den börjar med ett y:

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

Resultat av kodexekvering:

Skriptet matar ut 0 (noll) eftersom vi bad om felkoden för den senaste instruktionen som kördes. En kod på 0 betyder att skriptet kördes utan fel. Faktiskt variabeln $x innehåller strängen yandex, som börjar med tecknet "y". Annars kan "1" skrivas. Det är vackert bekväm väg skriptfelsökning.

Jämför strängar alfabetiskt i Bash

Uppgiften blir mer komplicerad när man försöker avgöra om en sträng är föregångaren till en annan sträng i stigande sorteringsordning. Människor som skriver skript i bash-skalet stöter ofta på två problem när det gäller operationer som är större än och mindre än när det gäller Linux-strängjämförelser, som har ganska enkla lösningar:

Först måste tecknen "större än" och "mindre än" escapes genom att lägga till ett omvänt snedstreck (\) framför dem, eftersom de annars kommer att behandlas av skalet som omdirigeringstecken och strängar som filnamn. Detta är ett av de fall där det är ganska svårt att spåra en bugg.

#!/bin/bash
# felaktig användning av strängjämförelseoperatorer
val1=baseball
val2=hockey
om [ $val1 > $val2 ]
sedan

annan

fi

Vad händer om du jämför bashsträngar:

Som du kan se gav symbolen "större än" enbart, i sin direkta form, felaktiga resultat, även om inga fel genererades. I det här fallet detta tecken gjorde att utdataströmmen omdirigerades, så inga syntaxfel hittades och, som ett resultat, en fil med namnet hockey:

För att åtgärda det här felet måste du escape tecknet ">" så att villkoret ser ut så här:

...
if [ $val1 \> $val2 ]
...

Då blir resultatet av programmet korrekt:

För det andra är strängarna ordnade med operatorerna "större än" och "mindre än" ordnade annorlunda än det händer med kommandot sortera. Här är problem svårare att känna igen, och de kanske inte uppstår alls om jämförelsen är skiftlägesokänslig. I ett lag sortera Och testa Jämförelsen är annorlunda:

#!/bin/bash
val1=Testar
val2=testning
if [ $val1 \> $val2 ]
sedan
echo "$val1 är större än $val2"
annan
echo "$val1 är mindre än $val2"
fi

Resultatet av koden:

I ett lag testa strängar med stora bokstäver kommer först att föregå strängar med små bokstäver. Men om samma data skrivs till en fil, som sedan tillämpa kommandot sortera, då kommer strängar med små bokstäver först:

Skillnaden mellan deras arbete är att testa för att bestämma sorteringsordningen tas arrangemanget av tecken enligt ASCII-tabellen som grund. I sortera den använder också den sorteringsordning som anges för språkinställningarna för regionala inställningar.

Kontrollerar en sträng för ett tomt värde

Jämförelse med operatorer -z Och -n används för att avgöra om en variabel innehåller innehåll. På så sätt kan du hitta tomma rader i bash. Exempel:

#!/bin/bash
val1=testning
val2=""
# kontrollerar om strängen är tom
if [ -n $val1 ]
sedan
echo "Strängen "$val1" är inte tom"
annan
echo "Strängen "$val1" är tom"
fi
# kontrollerar om strängen är tom
om [ -z $val2 ]
sedan
echo "Strängen "$val2" är tom"
annan
echo "Strängen "$val2" är inte tom"
fi
om [ -z $val3 ]
sedan
echo "Strängen "$val3" är tom"
annan
echo "Strängen "$val3" är inte tom"
fi

Resultatet av koden:

Det här exemplet skapar två strängvariabler - val1 Och val2. Drift -n avgör om en variabel har val1 icke-noll längd, och -z kontroller val2 Och val3 till noll. Det är anmärkningsvärt att den senare inte definierades förrän vid jämförelseögonblicket, men tolken anser att dess längd fortfarande är lika med noll. Denna nyans bör beaktas när olika kontroller scenarier. Och om du inte är säker på vilket värde som finns i variabeln och om det är inställt alls, bör du kontrollera det med operatorn -n eller -z och först då använda den för sitt avsedda syfte.

Det är värt att uppmärksamma funktionen -n. Om en odeklarerad eller tom variabel skickas till den för att testa, kommer den att returnera sant, inte falskt. I sådana fall bör du bifoga strängen (variabeln) som checkas in dubbla citattecken för att få det att se ut så här:

...
if [ -n "$val1" ]
...

Slutsatser

Det finns vissa nyanser i de presenterade Bash-strängjämförelserna som är värda att förstå för att förhindra skriptfel. Men det finns många sådana situationer i praktiken, så att komma ihåg allt (och ännu mer, att beskriva) kommer inte att fungera.

I Bash-skalskript kan vi utföra nummerjämförelser. För att utföra en sifferjämförelseoperation i Bash måste du använda tillståndet "test" inom en if eller loop. I det här inlägget kommer vi att berätta hur du jämför siffror i bash.

Operatörer för jämförelse av bashnummer

operatörvad gör hanexempel
-ekvjämför siffror i bash för likhet, returnerar 0 om likaom [ $a -eq $b ] då
-gejämföra tal i bash om de är större än eller lika. Resultat returnerar 0 om det är större än eller lika medom [ $a -ge $b ] då
-gtjämför siffror i bash om de är större än.om [ $a -gt $b ] då
-lejämför tal i bash om mindre än eller lika.om [ $a -le $b ] då
-ltjämför siffror i bash om mindre.om [ $a -lt $b ] då
-nejjämför tal i bash om de inte är lika eller inte.om [ $a -ne $b ] då

Exempel i detalj på nummerjämförelseoperatorer i Bash:

1. operatör-ekv

Denna operatör jämför siffror, kommer att kontrollera om värdet är lika eller inte. Om det är lika returneras 0.

# cat test.sh #!/bin/bash echo "ange variabelt värde" läs ett eko "ange variabelt värde" läs b om [ $a -eq $b ] sedan eko "Returvärde:: $?" echo "a och b är lika" else echo "Returvärde::$?" eko "a och b är inte lika" fi #

Avrättning:

# sh test.sh ange variabelvärde 2 ange variabelvärde 3 Returvärde:: 1 a och b är inte lika # sh test.sh ange variabelvärde 2 ange variabelvärde 2 Returvärde: 0 a och b är lika #

I exemplet ovan tog vi siffrorna 2 och 3 för första gången och systemet returnerade värdet 1, men när vi tog samma värden för a och b, returnerar variabeln noll.

2. operatör-ge

Denna operatör jämför siffror och kontrollerar värden större än eller lika med. Om värdet är större än eller lika med, är dess returvärde 0.

# cat test1.sh #!/bin/bash #diff program för -ge echo "ange värde för variabel" läs ett eko "ange värde för variabel b" läs b om [ $a -ge $b ] sedan eko "returvärde : :$?" echo "a är större än eller lika med b" annars echo "returvärde::$?" eko "a är inte större än eller lika med b" fi #

3. operatör -gt

Denna nummerjämförelseoperatör kommer att testa att antalet är större. Om värdet är större, returnerar det 0.

# cat test2.sh #!/bin/bash #differ för -gt b=100 eko "Ange ett värde större än 100" läs a om [ $a -gt $b ] sedan eko "Mycket bra" annars eko "Inte särskilt bra" fi

4. operatör-le

Denna nummerjämförelseoperatör kommer att testa värden för mindre än eller lika med. Om det är mindre än eller lika är returvärdet 0.

#diff program för -le b=5 eko "ange ett värde mindre än eller lika med 5" läs a om [ $a -le $b ] sedan eko "korrekt" annars eko "falskt" fi #

5. operatör-lt

Denna nummerjämförelseoperatör kommer att testa värden för mindre. Om siffran är mindre är returvärdet 0.

om annat tillstånd används i BASH-skript Ofta. Tillståndet i sig har en något märklig form [[ tillstånd ]]. Var uppmärksam på indragen. Utan dem kommer tillståndet inte att fungera. Jag tar med listan logiska operatorer för villkoret [[ ? ]]:

Lista över logiska operatorer som
används för konstruktionen if-then-else-fi

#!/bin/bash om [[ $1 > 2 ]] sedan # om [[ ? ]] eko $1" större än 2" annars # om inte sant eko $1" mindre än 2 eller 2" fi

En del av er kommer att tycka att jämställdhetsoperatorn -eq är märklig. Prova att använda bekanta operatorer >

Låt oss säga att du har ett skript och användarverifiering krävs. Om användaren inte är root kommer skriptet att stoppas.

#!/bin/bash if [ "$(whoami)" != "root" ]; upprepa sedan "Du har inte behörighet att köra $0." utgång1; fi

Ofta behöver du kontrollera en variabel för ett värde. Om det inte finns något i variabeln kan du stoppa skriptet.

#!/bin/bash if [ -n "$num" ]; sedan "variabeln har något och du kan starta en annan process" annars echo "tom variabel, stoppa skriptet" exit 0; fi

Om variabeln är tom kan den fyllas i.

#!/bin/bash if [ -z "$num" ]; sedan echo "variabeln är tom" num=1 annars eko "num="$num fi

En tom variabel kan tilldelas ett standardvärde. Denna post är kortare än i föregående exempel.

#!/bin/bash # Skriv DEFAULT if argument kommandorad saknas [ -z "$arg1" ] && arg1=DEFAULT eko $arg1

Att jämföra strängar i Bash orsakar inga problem förrän uppgiften uppstår att jämföra två strängar på ett skiftlägesokänsligt sätt. Jag kommer att ge flera alternativ för att lösa problemet som jag själv använder. En egenskap hos dessa lösningar är att endast använda de inbyggda funktionerna i Bash-skalet.

Först skapar jag två variabler str1 och str2 som innehåller strängarna som ska jämföras. De kommer att användas i följande kodexempel.

#!/bin/bash str1 = "Sträng att jämföra" str2 = "sträng att jämföra"

Den första versionen av den skiftlägesokänsliga strängjämförelsen som jag vill föreslå använder kontrollen av skalalternativ med det inbyggda shopt-kommandot.

shopt -s nocasematch [[ $str1 == $str2 ]] && echo "match" || echo "matchar inte" shopt -u nocasematch

Nästa version av skiftlägesokänslig strängjämförelse är baserad på principen att självgjuta strängar till ett vanligt fall. Denna kodvariant fungerar på Bash version 4 och senare. Använder den för mer tidig version Bash kommer att ge ett fel.

Så för att jämföra strängar cast med gemener kan du använda följande kod.

[[ " $( str1 , ) " == " $( str2 , ) " ]] && echo "match" || eko "matchar inte"

Om du vill kasta de jämförda strängarna till versal, då kan du använda följande kod.

[[ " $( str1 ^^ ) " == " $( str2 ^^ ) " ]] && echo "match" || eko "matchar inte"

Som alternativ, kan tvång av strängar till ett enda fall utföras vid tidpunkten för att deklarera variabler. Detta görs med det inbyggda kommandot declare shell.

För att deklarera en variabel som innehåller gemener, använd följande kod.

#!/bin/bash declare -l str = "Camel Case String"

Som ett resultat av exekvering av denna kod kommer variabeln str att innehålla en sträng med små bokstäver, trots att strängen som tilldelas skrevs med kamel. Du kan ändra skiftläge för en sträng som redan är inställd i en variabel enligt följande.

#!/bin/bash str = "Camel Case String" deklarera -l str str = $str echo $str

För att konvertera en sträng till versaler, i ovanstående kodexempel, bör du ändra anropet till kommandot declare, med -u-växeln istället för -l-växeln.

Nu kan en skift-okänslig strängjämförelse med kommandot declare göras enligt följande.

deklarera -l str1_l = $str1 deklarera -l str2_l = $str2 [[ $str1_l == $str2_l ]] && echo "match" || eko "matchar inte"

Alla de skiftlägesokänsliga strängjämförelser som diskuteras ovan kan användas när du skriver Bash-skript. Därför, om du använder Bash version 4 och högre, kan du välja den som du gillar bäst. Om Bash-versionen är mindre än 4, ska det första alternativet användas, och specificera nocasematch-alternativet med det inbyggda shopt-skalet.

Det här ämnet är det fjärde ämnet i bash-skalets språkcykel. Han kommer att tala om sådana kontrollstrukturer av språket som villkorliga uttalanden. Men innan du går vidare till deras beskrivning är det nödvändigt att uppehålla sig vid några nyanser som kommer att göra övervägandet av materialet nedan mer förståeligt.
Låt oss först titta på vad en lista med kommandon är. En kommandolista är ett enda kommando, en pipeline eller en sekvens av kommandon/pipelines separerade av en av följande operatorer: ";", "&&", "||", avslutad med semikolon.
; - Operatör för sekventiell exekvering av flera kommandon. Varje efterföljande kommando börjar köras först efter att det föregående har slutförts (oavsett om det är framgångsrikt eller inte);
&& - kommandoexekveringsoperatör endast efter framgångsrik exekvering av den föregående;
|| - sats för att exekvera ett kommando endast efter en felaktig exekvering av det föregående.
Koda framgångsrikt slutförandeär 0 och felaktig - inte noll (beror på typen av fel). Ej att förväxla med vanliga programmeringsspråk när 1 är sant och 0 är falskt.
Nu kan vi gå vidare till det direkta övervägandet av villkorliga uttalanden.

fallvariantoperatör

Den allmänna syntaxen för fallförklaringen är:

fallvärde i
mall1) lista1;;
mönster2 | mall3) list2;;
esac

Den logiska sekvensen för exekvering av ärendesatsen:
a) det första mönstret som matchar värdet genomsöks;
b) om den hittas, exekveras listan med kommandon som motsvarar den, avslutad med ";;";
c) kontrollen överförs till operatörerna efter konstruktionen av fallet.
Mönstret och listan är åtskilda av tecknet ")". Flera villkor kan motsvara en lista med kommandon, i vilket fall de måste separeras med symbolen "|".
I mallar kan du använda tecknen "*", "?", "", som beskrevs i cykelns andra ämne. Med deras hjälp kan du implementera en instruktion som fungerar som standard i switch-satsen för sådana språk som C, PHP.
Jag kommer att ge ett exempel på användningsfall:
echo -n "[Universal Viewer] Ange filnamn: "; läs File case "$File" i *.jpg|*.gif|*.png) eog $File ;; *.pdf) evince $File ;; *.txt) mindre $File ;; *.html) firefox $File ;; /dev/*) echo "Ja, det är läskiga filer." ;; *) echo "Ok, ok - inte så mångsidig." echo "Jag är inte bekant med den här filtypen. Jag vet inte hur jag ska visa den." ;; esac
Ett annat exempel på att använda fallkonstruktionen:
echo "Fel. Vem ska jag skicka meddelandet till?" echo "Till chef: b" echo "Till kollegor: c" echo "Till ingen: valfri nyckel" läs svarsfall $svar i b|B) mail –s "fellogg" chef< error.log;; c|C) mail –s "Help! error log" –c denis nick < error.log;; *) echo "error"; exit;; esac

Villkorlig operatör om

Den allmänna syntaxen för if-satsen är:

om lista1 då
lista 2

fi

De fyrkantiga parenteserna här indikerar valfria konstruktioner. Den logiska sekvensen för exekvering av ärendesatsen:
a) list1 exekveras;
b) om den exekveras utan fel, exekveras list2. Annars exekveras list3, och om den slutförs utan fel, list4. Om list3 också returnerar en felkod, exekveras list5;
c) kontrollen överförs till operatörerna efter if-konstruktionen.
Jag kommer att ge ett exempel på användning om:
om grep -q Bash-fil, upprepa "Filen innehåller minst ett Bash-ord." fi
När om och sedan är på samma rad, måste om och sedan-konstruktionerna sluta med semikolon. Till exempel:
$om[$? –ne0]; eka sedan "Fel"; fi
Nu vet vi att det är möjligt att lägga om och sedan på samma rad, låt oss skriva om exemplet ovan:
if grep -q Bash-fil; eka sedan "Filen innehåller ordet Bash." fi

testpåstående och villkorliga uttryck

I exemplet ovan, istället för att analysera utgångskoden, används en tillståndskontroll. De två formerna av ett sådant test är likvärdiga: det inbyggda testkommandot och [villkor]. Till exempel, för att kontrollera om en fil finns, skulle du skriva:
testa -e<файл>
eller
[-e<файл> ]
Om hakparenteser används måste de separeras från varandra med ett mellanslag, eftersom "[" är namnet på kommandot och "]" är det sista argumentet som krävs för att avsluta det.
Om villkoret kontrolleras framgångsrikt returneras 0, och om det är falskt är felkoden 1.
Testkommandot kan kontrollera om en sträng är tom. En icke-tom sträng resulterar i utgångskod 0. Tom, respektive - 1. Till exempel:
$ test $USER; echo $? 0
Konstruktionen "" är mer mångsidig än "". Denna utökade version av testkommandot. Inuti denna konstruktion utförs ingen ytterligare tolkning av filnamn och ingen uppdelning av argument i separata ord, utan ersättning av parametrar och kommandon är tillåten. Till exempel:
file=/etc/passwd om [[ -e $file ]] eka sedan "Lösenordsfil hittades." fi
Konstruktionen "" är mer att föredra än "" eftersom den hjälper till att undvika vissa logiska fel. Till exempel, operatorerna "&&", "||", "<" и ">" inuti "" är helt giltiga, medan inuti "" genererar felmeddelanden.
Konstruktionen "(())" tillåter beräkning av aritmetiska uttryck inuti den. Om resultatet av beräkningen är noll, returneras en felkod. Ett resultat av beräkningen som inte är noll ger en returkod på 0. Det vill säga raka motsatsen till testet och instruktionerna "" som diskuterats ovan.
If-satsen tillåter kapslade kontroller:
if echo "Nästa *om* är inuti den första *om*." om [[ $comparison = "heltal" ]] då ((a< b)) else [[ $a < $b ]] fi then echo "$a меньше $b" fi

Villkorsuttryck kan kombineras med reguljära uttryck. logiska operationer:
! <выражение>- förnekande;
<выражение1>-a<выражение2>- logiskt OCH;
<выражение1>-o<выражение2>- logiskt ELLER.

Elementära villkorliga uttryck för filer:
-e - fil finns;
-f - vanlig fil (inte katalog eller enhetsfil);
-s - filstorlek som inte är noll;
-d - filen är en katalog;
-b - filen är en blockenhet (diskett, cdrom, etc.);
-c - filen är en teckenenhet (tangentbord, modem, Ljudkort och så vidare.);
-p - filen är en pipe;
-h - filen är en symbolisk länk;
-L - filen är en symbolisk länk;
-S - filen är en socket;
-t - filen är associerad med en terminalenhet;
-r - filen är läsbar (för användaren som startade skriptet);
-w - filen är skrivbar (till användaren som körde skriptet);
-x - filen är tillgänglig för exekvering (för användaren som startade skriptet);
-g - (sgid) flaggan för fil eller katalog är inställd;
-u - (suid) flaggan för filen är satt;
-k - flaggan för sticky bit är satt;
-O - ​​du är ägaren till filen;
-G - du tillhör samma grupp som filen;
-N - filen har ändrats sedan den senaste läsningen;
fil1 -nt fil2 – fil1 är nyare än fil2;
fil1 -ot fil2 – fil1 är äldre än fil2;
fil1 -ef fil2 - fil1 och fil2 är hårda länkar till samma fil.

Elementära villkorliga uttryck för att jämföra strängar:
-z sträng – strängens längd är 0;
-n sträng – strängens längd är inte lika med 0;
sträng1 == sträng2 – strängar matchar (liknande "=");
line1 !== line2 – rader stämmer inte överens (liknar “!=”);
linje 1< строка2 – строка1 предшествует строке2 в лексикографическом порядке;
linje1 > rad2 - rad1 följer rad2 i lexikografisk ordning.
Ett aritmetiskt villkorligt uttryck har formatet:
argument1 operation argument2 där argumenten är heltal och följande operationer är tillåtna:
-eq - lika;
-ne - inte lika;
-lt - mindre;
-le - mindre än eller lika;
-gt - mer;
-ge - större än eller lika;
< - меньше (внутри двойных круглых скобок);
<= - меньше или равно (внутри двойных круглых скобок);
> - större än (inom dubbla parenteser);
>= - större än eller lika med (inom dubbla parenteser).

Låt oss skriva om det föregående exemplet med en if-sats:
echo "Fel. Vem ska jag skicka meddelandet till?" echo "Till chef: b" echo "Till kollegor: c" echo "Till ingen: någon nyckel" läs svaret if [ "$answer" == "b" –o "$answer" == "B" ]; sedan mail –s "fellogg"-chef< error.log; elif [ "$answer" == "c" –o "$answer" == "C" ]; then mail –s "Help! error log" –c denis nick < error.log; else echo "error"; exit; fi

I nästa ämne kommer jag att fortsätta att överväga bashskalets kontrollstrukturer. Slingoperatörer kommer nämligen att övervägas. Och nu väntar jag på kommentarer och kritik :).

UPD: Tack till användaren

Om du upptäcker ett fel, välj en textbit och tryck på Ctrl + Retur
DELA MED SIG: