[Bash/string2int/Annanlössning?] jömföra med störreän likamed o.s.v.

Permalänk
Medlem

[Bash/string2int/Annanlössning?] jömföra med störreän likamed o.s.v.

Hej!

Jag använder mig av "grep" och "wc -l" i bash skript för att få ut en siffra på en antal rader som inne håller ett vist ord,
hur som helst vill jag jämföra denna siffra mot en kontroll siffra men som ni kanske vet med wc -l får man ut en string, så nu vill jag göra om den till en int då mitt testskript visa att det inte funkar som jag hade hoppas med strings:

1 #! /bin/bash 2 str="5" 3 aStr="9" 4 if [ $aStr > $str ]; then 5 echo "Funkar" 6 else 7 echo "Funkar ej" 8 fi 9 if [ $str > $aStr ]; then 10 echo "Funkar ej" 11 else 12 echo "Funkar" 13 fi 14 if [ $str < $aStr ]; then 15 echo "Funkar" 16 else 17 echo "Funkar ej" 18 fi

Output:

bash testarn Funkar Funkar ej Funkar

Detta visar att en string jämförelse görs bara på antalet tecken inte på vad den faktiskt innehåller vilket är lite trist.

Om jag skulle få ut det i int istället hade jag ju kunna använda -le, -ge,-ne eller -eq om jag skulle vilja.

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Medlem
Skrivet av Mejan:

Ser inte riktigt problemet du har.
Exempelvis om jag kör:

#!/bin/bash str="5" aStr="9" bStr="5" set -x if [[ "$str" = "$aStr" ]]; then echo "$str" = "$aStr" fi if [[ "$str" = "$bStr" ]]; then echo "$str" = "$bStr" fi exit 0

Får jag:

+ [[ 5 = \9 ]] + [[ 5 = \5 ]] + echo 5 = 5 5 = 5 + exit 0

http://www.tldp.org/LDP/abs/html/untyped.html
http://www.gnu.org/software/bash/manual/bashref.html#Conditio...

Visa signatur

Arch - Makepkg, not war -||- Gigabyte X570 Aorus Master -||- GSkill 64GiB DDR4 14-14-15-35-1T 3600Mhz -||- AMD 5900x-||- Gigabyte RX6900XT -||- 2x Adata XPG sx8200 Pro 1TB -||- EVGA G2 750W -||- Corsair 570x -||- O2+ODAC-||- Sennheiser HD-650 -|| Boycott EA,2K,Activision,Ubisoft,WB,EGS
Arch Linux, one hell of a distribution.

Permalänk
Hedersmedlem
Skrivet av Mejan:

Hej!

Jag använder mig av "grep" och "wc -l" i bash skript för att få ut en siffra på en antal rader som inne håller ett vist ord,
hur som helst vill jag jämföra denna siffra mot en kontroll siffra men som ni kanske vet med wc -l får man ut en string, så nu vill jag göra om den till en int då mitt testskript visa att det inte funkar som jag hade hoppas med strings:

1 #! /bin/bash 2 str="5" 3 aStr="9" 4 if [ $aStr > $str ]; then 5 echo "Funkar" 6 else 7 echo "Funkar ej" 8 fi 9 if [ $str > $aStr ]; then 10 echo "Funkar ej" 11 else 12 echo "Funkar" 13 fi 14 if [ $str < $aStr ]; then 15 echo "Funkar" 16 else 17 echo "Funkar ej" 18 fi

Output:

bash testarn Funkar Funkar ej Funkar

Detta visar att en string jämförelse görs bara på antalet tecken inte på vad den faktiskt innehåller vilket är lite trist.

Om jag skulle få ut det i int istället hade jag ju kunna använda -le, -ge,-ne eller -eq om jag skulle vilja.

Man kan i Bash använda `<`- och `>`-operatorerna, men de måste escape:as i den "vanliga" `test`-funktionen med enkla klamrar:

#!/bin/bash str="5" aStr="9" if [ $aStr \> $str ]; then echo "Funkar" else echo "Funkar ej" fi if [ $str \> $aStr ]; then echo "Funkar ej" else echo "Funkar" fi if [ $str \< $aStr ]; then echo "Funkar" else echo "Funkar ej" fi

ger vid körning:

$ ./test Funkar Funkar Funkar

`<` och `>` har annars speciella betydelser som omdirigeringsvariabler i skalet, vilket gör att dina test inte gör vad du tror att de gör.

Dock så är detta snarare en slump än något annat att det fungerar i detta fall. Dessa operatorer gör bara just en strängjämförelse plats för plats, så om vi skulle byta ut `str="5"` mot `str="511"` så skulle skriptet fortfarande tycka att `str` är "mindre än" `aStr`, eftersom `5` är före `9` i ASCII-tabellen:

#!/bin/bash str="511" aStr="9" if [ $aStr \> $str ]; then echo "Funkar" else echo "Funkar ej" fi if [ $str \> $aStr ]; then echo "Funkar ej" else echo "Funkar" fi if [ $str \< $aStr ]; then echo "Funkar" else echo "Funkar ej" fi

ger output som ovan:

$ ./test Funkar Funkar Funkar

Dold text

Använd i stället just `-le` och `-ge` här. Då använder ditt skript dessutom inga Bashspecifika konstruktioner, så `#!/bin/bash` kan bytas ut mot `#!/bin/sh`, vilket gör det mer portabelt och troligen snabbare, även om det senare sällan spelar någon större roll. Du behöver inte göra mer än att byta ut operatorerna direkt mot `-le` och `-ge`:

#!/bin/bash str="5" aStr="9" if [ $aStr -ge $str ]; then echo "Funkar" else echo "Funkar ej" fi if [ $str -ge $aStr ]; then echo "Funkar ej" else echo "Funkar" fi if [ $str -le $aStr ]; then echo "Funkar" else echo "Funkar ej" fi

ger återigen:

$ ./test Funkar Funkar Funkar

samtidigt som det korrekt hanterar exempelvis `str="511"`.

Ditt problem med `wc -l`-output är kanske snarare att den sträng du får lagrar innehåller mer än bara ett heltal vilket gör att Bash inte kan tolka det direkt som ett sådant. Det kan du lösa genom `cut`, `awk`, `sed`, `grep`, variabelsubstitution eller något liknande.

Visa signatur

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Permalänk
Medlem

Ja det funkade ju bra. Ett annat problem med strings som jag dock lyckas lösa var:

str1="1" str2="2" str2=$str1+$str2 echo "str2 efter plus: $str2"

Output:

str2 efter plus: 1+2

men om man skrev om till:

str1="1" str2="2" str2=$(($str1+$str2)) echo "str2 efter plus: $str2"

så vart outputen:

str2 efter plus: 3

Visa signatur

Смерть -это решение всех проблем. Нет человека - нет проблемы
Comp1: Ubuntu 16.04 Comp2: Arch Linux
Comp3: Ubuntu Server 16.04 Comp4: Centos 6.5
Comp5: Linux mint 16 Comp6: Raspberry pi (olika OS hela tiden)
Phone: Motorola Google Nexus 6

Permalänk
Hedersmedlem
Skrivet av Mejan:

Ja det funkade ju bra. Ett annat problem med strings som jag dock lyckas lösa var:

str1="1" str2="2" str2=str1+str2 echo "str2 efter plus: $str2"

Output:

str2 efter plus: 1+2

Nej, så blir det inte. Skalet vet ingenting om värdet av variablerna här, utan output skulle snarare bli:

str2 efter plus: str1+str2

Du menar nog snarare att rad 3 skulle se ut enligt:

str2=$str1+$str2

Vad som händer är har inget med aritmetik att göra, utan skalet kommer helt enkelt se att den har variabler i högerledet och översätta de till dess innehåll, så `$str1` ersätts med dess innehåll `1` och `$str2` med `2`, och då säger du egentligen bara att du vill att `$str2` framöver ska innehålla strängen "1+2". Ditt `+` och innehållet i `str1` och `str2` hade kunnat vara vilka giltiga strängar som helst (fast du åker på problem om de innehåller vitutrymme eftersom du inte kapslat in tilldelningen i citationstecken här).

Skrivet av Mejan:

men om man skrev om till:

str1="1" str2="2" str2=$((str1+str2)) echo "str2 efter plus: $str2"

så vart outputen:

str2 efter plus: 3

Ja, `$(())` är så kallad aritmetisk expansion och är syntaxen för att utföra enkel heltalsaritmetik i ett standardskal.

Som länken Commander gav ovan säger så är variabler i Bash (och liknande skal) inte typade, så egentligen är allt strängar, som sedan kan tolkas på olika sätt beroende på omgivning.

Visa signatur

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.