Sida 1 av 1
Numerisk jämförelse i Bash
Postat: 06 jan 2014, 14:37
av Johnny Rosenberg
Har ett litet problem här. Håller på med ett litet skript här och några rader i skriptet ägnar sig lite åt villkor med numeriska värden inblandade. Värdena slumpas fram och sparas i x så att 000000 ≤ x ≤ 999999.
Nu vill jag dock utesluta alla nummer som startar med 0, så:
Kod: Markera allt
if (( x < 10**5 )); then
#gör någonting
else
#gör någonting annat
fi
Problemet tycks vara att tal som startar med 0 ses som oktala och om en siffra > 7 ingår där (ej tillåtet i oktala tal) så blir det ett felmeddelande istället.
Finns något enkelt sätt att kringgå detta, eller måste jag göra en strängjämförelse istället?
Re: Numerisk jämförelse i Bash
Postat: 06 jan 2014, 14:43
av Johnny Rosenberg
I och för sig, i och med att jag vet att x alltid är 6 tecken långt så kan jag ju kringgå det hela med, som jag nämnde, en strängjämförelse:
Kod: Markera allt
if [[ $x < "100000" ]]; then
# Gör någonting
else
# Gör någonting helt annat
fi
Men det skulle ändå vara intressant att få svar på den ursprungliga frågan. Kanske kan vara användbart vid något annat tillfälle…
Re: Numerisk jämförelse i Bash
Postat: 06 jan 2014, 22:04
av mcNisse
Det finns ett enkelt sätt filtrera variabler.
${var#mönster} variabeln var filtreras från starten utfrån mönster.
% filtrerar bakifrån och dubbla förekomster filtrerar den längsta matchande strängen.
matchar ingen returneras orginalvärdet.
tex
I exemplet i frågan blir då
Kod: Markera allt
if (( ${x#0*} < 10**5 )); then
#gör någonting
else
#gör någonting annat
fi
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 00:14
av Johnny Rosenberg
mcNisse skrev:Det finns ett enkelt sätt filtrera variabler.
${var#mönster} variabeln var filtreras från starten utfrån mönster.
% filtrerar bakifrån och dubbla förekomster filtrerar den längsta matchande strängen.
matchar ingen returneras orginalvärdet.
tex
Ah, visst ja, tänkte inte på det. Borde skriva skript lite oftare så att jag blir van vid de olika sätten att göra saker på. Har i alla fall märkt att det går lite lättare numera och jag behöver inte söka upp precis allting, en del sitter faktiskt kvar i minnet. Dock ej just detta, tydligen.
Hur som helst, testade just ditt exempel:
Den tog bara bort en nolla, som synes.
Ska läsa på lite om detta så får vi se om jag kommer fram till en lösning innan jag bestämmer mig för att det är viktigare att sova…
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 00:20
av Johnny Rosenberg
Hittade en lösning som fungerar, men tyvärr förstår jag den inte till fullo. Någon som orkar förklara? Ska själv söka efter svaret också, givetvis.
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 00:25
av mcNisse
Det stämmer bra... Jag testade bara med en inledande 0 :-( Inget bra exempel :-(
Du får lov att använda ## om du vill ta bort flera.
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 00:39
av Johnny Rosenberg
Det verkar som att följande också fungerar:
Det vill säga vanlig substitution. Hittade inte denna form när jag letade men fann att följande också bara tar bort en nolla i början av strängen (i slutet om man byter # mot %):
Så det verkar som att +() innebär ”en eller flera av det som står inom parentesen”. Tar jag bort pluset fungerar det inte, tar jag bort parentesen fungerar det inte heller. Jag har dock inte hittat någon manual som säger att det är på detta sättet, utan bara kommit på det med hjälp av diverse experimenterande.
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 00:51
av Johnny Rosenberg
mcNisse skrev:Det stämmer bra... Jag testade bara med en inledande 0 :-( Inget bra exempel :-(
Du får lov att använda ## om du vill ta bort flera.
Det verkar inte heller fungera:
Tvåan försvann också.
Tycker i och för sig att det borde fungera, kanske en bugg?
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 08:12
av mcNisse
Jag tänkte inte igenom problemet tillräckligt bra
Kommandot använder sig av glob göra matchningen. Det gör att det inte finns någon sätt att matcha en eller flera tecken i början av en sträng.
Som tur är använder sig bash av extglob. Detta ger ytterligare några varianter att använda sig av:
?(<PATTERN-LIST>) Matches zero or one occurrence of the given patterns
*(<PATTERN-LIST>) Matches zero or more occurrences of the given patterns
+(<PATTERN-LIST>) Matches one or more occurrences of the given patterns
@(<PATTERN-LIST>) Matches one of the given patterns
!(<PATTERN-LIST>) Matches anything except one of the given patterns
Detta förklarar hur ${x/#+(0)/} fungerar, substituera 1 ellel flera 0 i början av strängen mot tomma strängen.
En annan variant med ## operatorn blir ${x##+(0)}.
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 20:18
av Johnny Rosenberg
mcNisse skrev:Jag tänkte inte igenom problemet tillräckligt bra
Kommandot använder sig av glob göra matchningen. Det gör att det inte finns någon sätt att matcha en eller flera tecken i början av en sträng.
Som tur är använder sig bash av extglob. Detta ger ytterligare några varianter att använda sig av:
?(<PATTERN-LIST>) Matches zero or one occurrence of the given patterns
*(<PATTERN-LIST>) Matches zero or more occurrences of the given patterns
+(<PATTERN-LIST>) Matches one or more occurrences of the given patterns
@(<PATTERN-LIST>) Matches one of the given patterns
!(<PATTERN-LIST>) Matches anything except one of the given patterns
Detta förklarar hur ${x/#+(0)/} fungerar, substituera 1 ellel flera 0 i början av strängen mot tomma strängen.
En annan variant med ## operatorn blir ${x##+(0)}.
Ja, det verkar ju bra, allt det där. En sak som jag stör mig lite på är ändå att man prompt måste ha sitt eget sätt att göra det på. Som användare måste man då lära sig flera olika syntaxer för samma sak. Vad kan man göra med ovanstående syntax som man inte kan göra med den syntax som exempelvis sed använder?
Var hittade du detta någonstans förresten? Jag har letat som en idiot efter detta, men inte funnit något läsvärt… Jag söker uppenbarligen efter fel saker…
Tackar för informationen!
Re: Numerisk jämförelse i Bash
Postat: 07 jan 2014, 22:33
av mcNisse
glob är enklare en reguljära uttryck.
Här har du länken.
http://wiki.bash-hackers.org/syntax/pattern
Re: Numerisk jämförelse i Bash
Postat: 09 jan 2014, 12:48
av Konservburk
Johnny Rosenberg skrev:Problemet tycks vara att tal som startar med 0 ses som oktala och om en siffra > 7 ingår där (ej tillåtet i oktala tal) så blir det ett felmeddelande istället.
Finns något enkelt sätt att kringgå detta, eller måste jag göra en strängjämförelse istället?
Du kan explicit ange att talet är decimalt även om det börjar med noll:
Kod: Markera allt
x=089
if (( 10#$x == 89 ))
then echo ja
else echo nej
fi
Re: Numerisk jämförelse i Bash
Postat: 10 jan 2014, 18:57
av Johnny Rosenberg
Konservburk skrev:Du kan explicit ange att talet är decimalt även om det börjar med noll:
Kod: Markera allt
x=089
if (( 10#$x == 89 ))
then echo ja
else echo nej
fi
Oj, det där var något nytt för mig! Har du någon länk där man kan läsa mer om detta?
Re: Numerisk jämförelse i Bash
Postat: 12 jan 2014, 11:23
av Konservburk
Johnny Rosenberg skrev:Oj, det där var något nytt för mig! Har du någon länk där man kan läsa mer om detta?
http://www.gnu.org/software/bash/manual ... metic.html
Constants with a leading 0 are interpreted as octal numbers. A leading ‘0x’ or ‘0X’ denotes hexadecimal. Otherwise, numbers take the form [base#]n, where the optional base is a decimal number between 2 and 64 representing the arithmetic base, and n is a number in that base. If base# is omitted, then base 10 is used. The digits greater than 9 are represented by the lowercase letters, the uppercase letters, ‘@’, and ‘_’, in that order. If base is less than or equal to 36, lowercase and uppercase letters may be used interchangeably to represent numbers between 10 and 35.