Stränghantering i sh (eller i nödfall i bash)?

Här diskuterar vi skal, kommandon och klassiska linuxverktyg.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Har ett litet problem som jag gärna, om möjligt, vill ha en lösning på på ren skriptnivå.

Jag håller på att utveckla ett enkelt skript som jag gjort vid ett tidigare tillfälle. Istället för att fördefiniera allt i variabler vill jag läsa in dem via dialogrutor istället (under förutsättning att användaren vill det, annars vill jag ha variablerna inlästa från en fil, men det blir ett senare problem).

Många av variablerna är sökvägar och jag använder Xdialog --dselect och Xdialog --fselect för att låta användaren välja sina sökvägar resprktive filer. När det gäller val av mappar uppstår ett litet dilemma: Efter att ha valt en mapp returneras en sökväg med följande utseende, exempelvis:

Kod: Markera allt

/home/guraknugen/Eget/
I de flesta fall i mitt skript vill ja hellre ha följande form:

Kod: Markera allt

/home/guraknugen/Eget
Detta gör det möjligt att använda båda varianterna då jag enkelt, vid behov, bara kan infoga ett snedstreck, exempelvis:

Kod: Markera allt

MINMAPP=`Xdialog --stdout --dselect bla bla bla bla`
MINFIL="${MINMAPP}/FinFil.mjölk"
Så min fråga är: Finns det några inbyggda stränghanteringsfunktioner som man kan använda i sh-skript, som motsvarar exempelvis BASIC-funktionerna RIGHT, LEFT, MID och LEN? Då skulle vara enkelt att plocka bort sista tecknet.

Eller måste jag använda sed (som jag för övrigt är väldigt mycket nybörjare på)?
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Lars
Inlägg: 6191
Blev medlem: 14 jan 2007, 19:31
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Ort: Stockholm

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Lars »

Ett enkelt sätt är att bara acceptera att det blir dubbla snedstreck, det fungerar ändå ;)
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Konservburk »

Det går att plocka bort det avslutande / om du nu vill det...
använd "${MINMAPP%/}" istället för "${MINMAPP}".
Användarvisningsbild
mcNisse
Inlägg: 5211
Blev medlem: 06 feb 2007, 20:51
OS: Debian
Utgåva: Vet inte/ingen utgåva passar

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av mcNisse »

Det där är inte bourne shell...
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Konservburk »

mcNisse skrev:Det där är inte bourne shell...
Du menar ${VAR%/} ? Jag ser inte att någon efterfrågar att det ska fungera med orinal bourne shell från 70-talet. Den där konstruktionen är giltig posix sh och fungerar med alla moderna varianter av /bin/sh.
Användarvisningsbild
mcNisse
Inlägg: 5211
Blev medlem: 06 feb 2007, 20:51
OS: Debian
Utgåva: Vet inte/ingen utgåva passar

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av mcNisse »

Det viste jag inte...
Jag har haft problem med sh på HPUX.
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Konservburk »

mcNisse skrev:Det viste jag inte...
Jag har haft problem med sh på HPUX.
Har aldrig använt HPUX sh. Det är möjligt att den inte är posix-kompatibel. Jag har för mig att SunOS sh inte heller klarar av det. Den som är nyfiken kan läsa vad ett posix-kompatibelt sh ska klara här:

http://www.opengroup.org/onlinepubs/009 ... hap02.html
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Såg att det droppat in en del svar, men jag tar väl ett i taget…
Lars skrev:Ett enkelt sätt är att bara acceptera att det blir dubbla snedstreck, det fungerar ändå ;)
Jo, men i vissa fall vill jag ju ha utan avslutande snedstreck, typ:

Kod: Markera allt

#!/bin/sh
A="${HOME}/Eget"
B="/media/Backup/guraknugen"
C="${HOME}/.LogBackup"
D="${HOME}/.ExcludedFromBackup"

rsync -auv --exclude-from ${D} --delete-during --delete-excluded "${A}" "${B}/" >> "${C}"
Här har jag ju lagt till ett snedstreck för B men inte till de övriga sökvägarna. Jag föredrar att lägga till dem i koden istället för att ha dem i variablerna. Det gör det lättare att hålla sig konsekvent. Då vet jag att sökvägarna ALDRIG slutar med snedstreck och kan bara pytsa dit dem där det behövs.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Konservburk skrev:Det går att plocka bort det avslutande / om du nu vill det...
använd "${MINMAPP%/}" istället för "${MINMAPP}".
Det där ser ju smidigt ut. Kan du förklara hur man ska tänka? Vad hade du gjort om du velat ta bort de 5 siste tecknen, exempelvis? Eller om du hade velat ta bort sista steget i sökvägen?

Eller med andra ord:

Kod: Markera allt

/min/intressanta/sökväg/ → /min/intressanta/sö # 5 sista tecknen borttagna
/min/intressanta/sökväg/ → /min/intressanta # sista nivån borttagen samt sista snedstrecket
Varför jag frågar är för att det bär mig emot att ha med saker i min kod om jag inte vet hur det fungerar. Annars blir det lätt så att man råkar på ett liknande problem, men eftersom man inte vet hur den förra lösningen fungerar så kan man inte modifiera den till den nya situationen.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Johnny Rosenberg skrev:Eller med andra ord:

Kod: Markera allt

/min/intressanta/sökväg/ → /min/intressanta/sö # 5 sista tecknen borttagna
/min/intressanta/sökväg/ → /min/intressanta # sista nivån borttagen samt sista snedstrecket
Varför jag frågar är för att det bär mig emot att ha med saker i min kod om jag inte vet hur det fungerar. Annars blir det lätt så att man råkar på ett liknande problem, men eftersom man inte vet hur den förra lösningen fungerar så kan man inte modifiera den till den nya situationen.
Den senare kom jag på:

Kod: Markera allt

A="/min/intressanta/sökväg/"
A=${A%/*/}
Verkar fungera i alla fall, sedan om det är rätt är kanske en annan sak…
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Konservburk »

Johnny Rosenberg skrev:
Konservburk skrev:Det går att plocka bort det avslutande / om du nu vill det...
använd "${MINMAPP%/}" istället för "${MINMAPP}".
Det där ser ju smidigt ut. Kan du förklara hur man ska tänka? Vad hade du gjort om du velat ta bort de 5 siste tecknen, exempelvis? Eller om du hade velat ta bort sista steget i sökvägen?

Eller med andra ord:

Kod: Markera allt

/min/intressanta/sökväg/ → /min/intressanta/sö # 5 sista tecknen borttagna
/min/intressanta/sökväg/ → /min/intressanta # sista nivån borttagen samt sista snedstrecket
Varför jag frågar är för att det bär mig emot att ha med saker i min kod om jag inte vet hur det fungerar. Annars blir det lätt så att man råkar på ett liknande problem, men eftersom man inte vet hur den förra lösningen fungerar så kan man inte modifiera den till den nya situationen.
De fem sista tecknen skulle jag tagit bort så här: "${A%?????}", dvs fem stycken ? efter varandra. Detta eftersom ? matchar ett enda tecken, vilket som helst. Att ta bort "sista steget" går att göra precis som du redan listat ut med "${A%/*/}", förutsatt att det finns ett och endast ett / på slutet.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Konservburk skrev:
Johnny Rosenberg skrev:
Konservburk skrev:Det går att plocka bort det avslutande / om du nu vill det...
använd "${MINMAPP%/}" istället för "${MINMAPP}".
Det där ser ju smidigt ut. Kan du förklara hur man ska tänka? Vad hade du gjort om du velat ta bort de 5 siste tecknen, exempelvis? Eller om du hade velat ta bort sista steget i sökvägen?

Eller med andra ord:

Kod: Markera allt

/min/intressanta/sökväg/ → /min/intressanta/sö # 5 sista tecknen borttagna
/min/intressanta/sökväg/ → /min/intressanta # sista nivån borttagen samt sista snedstrecket
Varför jag frågar är för att det bär mig emot att ha med saker i min kod om jag inte vet hur det fungerar. Annars blir det lätt så att man råkar på ett liknande problem, men eftersom man inte vet hur den förra lösningen fungerar så kan man inte modifiera den till den nya situationen.
De fem sista tecknen skulle jag tagit bort så här: "${A%?????}", dvs fem stycken ? efter varandra. Detta eftersom ? matchar ett enda tecken, vilket som helst. Att ta bort "sista steget" går att göra precis som du redan listat ut med "${A%/*/}", förutsatt att det finns ett och endast ett / på slutet.
Aha, jag försökte med ”.” som i en del sammanhang brukar betyda ”ett valfritt tecken”, men det gick givetvis inte. Märkte också att om man skriver en teckenkombination som inte stämmer med hur strängen ser ut, så struntar den bara i att göra något…

Verkar som att % betyder ”slutet av strängen” och jag läste mig just till att # är dess motsats, samt att man även kan använda %% och ##. Tyckte det kändes väldigt primitivt när jag läste om det, men man kanske kan göra mer än man tror med dem.

Finns det också sätt att ta bort tecken mitt i textsträngen eller tvärt om, eller blir man tvungen att blanda in sed då?
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Konservburk »

Johnny Rosenberg skrev:Verkar som att % betyder ”slutet av strängen” och jag läste mig just till att # är dess motsats, samt att man även kan använda %% och ##. Tyckte det kändes väldigt primitivt när jag läste om det, men man kanske kan göra mer än man tror med dem.
Det går att göra mycket mer än man först tror, speciellt när man börjar kombinera dem.
Johnny Rosenberg skrev:Finns det också sätt att ta bort tecken mitt i textsträngen eller tvärt om, eller blir man tvungen att blanda in sed då?
Du kan använda # % ## %% upprepade gånger. Sedan har bash även "${VAR/a/b}" och "${VAR//a/b}" för att ersätta mitt i, men då är det ju inte sh längre.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Konservburk skrev:
Johnny Rosenberg skrev:Finns det också sätt att ta bort tecken mitt i textsträngen eller tvärt om, eller blir man tvungen att blanda in sed då?
Du kan använda # % ## %% upprepade gånger. Sedan har bash även "${VAR/a/b}" och "${VAR//a/b}" för att ersätta mitt i, men då är det ju inte sh längre.
Kanske är dumt att begränsa sig till sh, i och för sig, när bash verkar bättre, i alla fall när det gäller de skillnader jag sett. Man måste ju inte vara kompatibel med allt…
Det vanliga sh verkar ju också oerhört bökigt när det gäller att göra enkla matematiska beräkningar, då man tydligen måste blanda in externa program för att få jobbet gjort, exempelvis expr. Extra komiskt blir det när det visar sig att ett uttryck som ”expr 2 * 3” inte är giltigt, utan man istället måste skriva ”expr 2 \* 3”. Mycket sådant och koden blir ganska svårläst… Har fått för mig att enkla beräkningar låter sig göras mycket enklare och snyggare i bash, men jag är inte så påläst när det gäller bash. På den gamla goda tiden (slutet av 1980-talet) när man larvade sig lite i Unix så var det tcsh och csh som gällde där jag befann mig, men förmodligen är bash bättre.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Konservburk »

Johnny Rosenberg skrev:Kanske är dumt att begränsa sig till sh, i och för sig, när bash verkar bättre, i alla fall när det gäller de skillnader jag sett. Man måste ju inte vara kompatibel med allt…
Det vanliga sh verkar ju också oerhört bökigt när det gäller att göra enkla matematiska beräkningar, då man tydligen måste blanda in externa program för att få jobbet gjort, exempelvis expr. Extra komiskt blir det när det visar sig att ett uttryck som ”expr 2 * 3” inte är giltigt, utan man istället måste skriva ”expr 2 \* 3”. Mycket sådant och koden blir ganska svårläst… Har fått för mig att enkla beräkningar låter sig göras mycket enklare och snyggare i bash, men jag är inte så påläst när det gäller bash.
Du kan göra enkla beräkningar även med sh utan att blanda in expr alls:

Kod: Markera allt

echo $((2+3))
Då pratar jag åter igen om posix sh, till skillnad från antika varianter. Jag påminner även om länken som tar upp syntaxen:

http://www.opengroup.org/onlinepubs/009 ... hap02.html
Johnny Rosenberg skrev:På den gamla goda tiden (slutet av 1980-talet) när man larvade sig lite i Unix så var det tcsh och csh som gällde där jag befann mig, men förmodligen är bash bättre.
Antar att det var BSD-grenen av Unix till skillnad från systemV-grenen.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Konservburk skrev:
Johnny Rosenberg skrev:På den gamla goda tiden (slutet av 1980-talet) när man larvade sig lite i Unix så var det tcsh och csh som gällde där jag befann mig, men förmodligen är bash bättre.
Antar att det var BSD-grenen av Unix till skillnad från systemV-grenen.
Jag var mer fokuserad på skolarbetet på den tiden, men som jag fattade det så var det båda, om nu det är möjligt. Om inte, så var det Berkeley.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
David Andersson
Inlägg: 1269
Blev medlem: 15 dec 2007, 03:20
OS: Xubuntu

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av David Andersson »

Johnny Rosenberg skrev: Eller om du hade velat ta bort sista steget i sökvägen?

Eller med andra ord:

Kod: Markera allt

/min/intressanta/sökväg/ → /min/intressanta/sö # 5 sista tecknen borttagna
/min/intressanta/sökväg/ → /min/intressanta # sista nivån borttagen samt sista snedstrecket
Ta ut delsträngar

Förutom att plocka bort saker i parameterexpansion kan man använda nån av kommandona basename, dirname och expr .

Exempel

Kod: Markera allt

dirname /a/b/c
basename /a/b/c
expr "abc47def" : "[^0-9]*\([0-9]*\)"

dir=$(dirname "$mypath")
base=$(basename "$mypath")
digits=$(expr "$mystring" : "[^0-9]*\([0-9]*\)")
(Basename och dirname är gjorda så att när man plockat isär en path med dem så kan man sätta ihop delarna med / emellan och få tillbaka samma path. Inte alltid samma sträng, men en path som går till samma ställe. Den förstår dubbla // och sånt.)

Testa på delsträngar

Om man inte behöver en delsträng explicit utan bara ska göra en test av förekomsten av en delsträng kan man använda [[ ... =~ ...]], expr, och inte att glömma case.

Exempel

Kod: Markera allt

expr "abba" : ".*bb"   # 3, abba innehåller bb
expr "abba" : ".*cc"   # 0, innehåller inte cc

if expr "$mystring" : ".*buntu"; then echo "Yeah!"; fi

if [[ "$mystring" =~ "buntu" ]]; then echo "Yeah!"; fi

case "$mystring" in
    *buntu*) echo "Yeah!";;
    *indow*) echo "Yack!";;
    *) echo "Åh, vet inte";;
esac
I expr finns vanlig tråkig substr, men den använder man aldrig. Påminner alldeles för myckt om Basic och Java.

Exempel

Kod: Markera allt

expr substr "abba" 2 2    # returnerar bb
(Edit: [[ ... ]] finns inte i sh)
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

David Andersson skrev:Ta ut delsträngar

Förutom att plocka bort saker i parameterexpansion kan man använda nån av kommandona basename, dirname och expr .

Exempel

Kod: Markera allt

dirname /a/b/c
basename /a/b/c
expr "abc47def" : "[^0-9]*\([0-9]*\)"

dir=$(dirname "$mypath")
base=$(basename "$mypath")
digits=$(expr "$mystring" : "[^0-9]*\([0-9]*\)")
(Basename och dirname är gjorda så att när man plockat isär en path med dem så kan man sätta ihop delarna med / emellan och få tillbaka samma path. Inte alltid samma sträng, men en path som går till samma ställe. Den förstår dubbla // och sånt.)
Det lustiga är att jag själv redan tittat på både dirname och basename, men dömde ut dem efter några snabba tester, för de gjorde inte det jag ville. Men nu när du åter tar upp det hela gjorde jag flera tester och fann att de visst gör det jag vill, om man bara tänker till lite.

Vad jag har som utgångspunkt är ju följande:

Kod: Markera allt

/a/b/c/
Vad jag vill ha är detta;

Kod: Markera allt

/a/b/c
Den enkla sats som fixar detta ser givetvis ut så här, om sökvägen finns i variabeln ”a”:

Kod: Markera allt

MyPath="$(dirname $a)/$(basename $a)"
Alternativ:

Kod: Markera allt

MyPath="`dirname $a`/`basename $a`"
En liten följdfråga bara, när det gäller skalprogrammering (sh) i allmänhet:
Kan man alltid ersätta `<uttryck>` med $(<uttryck>) eller är detta bara ett specialfall? Båda varianterna fungerade i alla fall, men ` sitter lite avigt till på mitt tangentbord, trots att jag gjort min egen layout. Använder jag $() istället slipper jag ju göra om min tangentbordslayout igen…
David Andersson skrev:I expr finns vanlig tråkig substr, men den använder man aldrig. Påminner alldeles för myckt om Basic och Java.

Exempel

Kod: Markera allt

expr substr "abba" 2 2    # returnerar bb
(Edit: [[ ... ]] finns inte i sh)
Fast å andra sidan, om något är tråkigt eller inte spelar ju mindre roll om enda målet är att få jobbet gjort. Jag har lättare att köpa argument som de mer handlar om prestanda och dylikt. När jag själv hittar flera olika alternativ och ska välja ett brukar jag ta tid på dem. Skiljer det mycket tar jag det snabbaste. Skiljer det lite kanske jag väljer det som ser mest lättläst ut eller som slukar minst resurser eller det som bäst matchar koden i övrigt. Men snabbhet är prio 0 för mig. Eller prio 1 kanske man brukar säga.

I just detta fall visade sig båda vara lika snabba. Ibland var den ena lite snabbare, ibland den andra. Här är en av testerna:

Kod: Markera allt

$ a="/home/guraknugen/Eget/"
$ time for i in $(seq 1 1000); do b="$(dirname $a)/$(basename $a)"; done

real	0m9.523s
user	0m4.392s
sys	0m5.324s
$ time for i in $(seq 1 1000); do b="`dirname $a`/`basename $a`"; done

real	0m9.585s
user	0m4.292s
sys	0m5.276s
$ echo $b
/home/guraknugen/Eget
I stort sett samma tid tog det, som synes. Det blir som sagt lite olika varje gång.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Konservburk »

Johnny Rosenberg skrev:En liten följdfråga bara, när det gäller skalprogrammering (sh) i allmänhet:
Kan man alltid ersätta `<uttryck>` med $(<uttryck>) eller är detta bara ett specialfall? Båda varianterna fungerade i alla fall, men ` sitter lite avigt till på mitt tangentbord, trots att jag gjort min egen layout. Använder jag $() istället slipper jag ju göra om min tangentbordslayout igen…
$() och `` är i princip identiska. Det skiljer en del när de gäller nästling, men det är inget du behöver bry dig om du inte ska ha väldigt mycket kod innuti dem (t.ex. hela case-satser).

Annars är den stora skillnaden att `` fungerar med alla sh som finns (inklusive orginalet från 70-talet), medan $() bara fungerar med posix-kompatibla sh. Jag brukar hur som hest hålla mig till $() eftersom den är mer lättläst.
Johnny Rosenberg skrev:Fast å andra sidan, om något är tråkigt eller inte spelar ju mindre roll om enda målet är att få jobbet gjort. Jag har lättare att köpa argument som de mer handlar om prestanda och dylikt. När jag själv hittar flera olika alternativ och ska välja ett brukar jag ta tid på dem. Skiljer det mycket tar jag det snabbaste. Skiljer det lite kanske jag väljer det som ser mest lättläst ut eller som slukar minst resurser eller det som bäst matchar koden i övrigt. Men snabbhet är prio 0 för mig. Eller prio 1 kanske man brukar säga.

I just detta fall visade sig båda vara lika snabba. Ibland var den ena lite snabbare, ibland den andra. Här är en av testerna:

Kod: Markera allt

$ a="/home/guraknugen/Eget/"
$ time for i in $(seq 1 1000); do b="$(dirname $a)/$(basename $a)"; done

real	0m9.523s
user	0m4.392s
sys	0m5.324s
$ time for i in $(seq 1 1000); do b="`dirname $a`/`basename $a`"; done

real	0m9.585s
user	0m4.292s
sys	0m5.276s
$ echo $b
/home/guraknugen/Eget
I stort sett samma tid tog det, som synes. Det blir som sagt lite olika varje gång.
Det som tar upp den mesta tiden där är fork:andet av dirname och basename. Använder du istället b="${a%/}" så lär det gå betydligt snabbare. Å andra sidan fungerar det då bara om det inte finns fler än ett / på slutet. Är man lite kreativ går den biten också att komma runt, iofs med risk för att det blir onödigt svårläst.

Kod: Markera allt

$ time for i in $(seq 1 1000); do b="$(dirname $a)/$(basename $a)"; done

real    0m1.787s
user    0m0.423s
sys     0m1.353s
$ time for i in $(seq 1 1000); do b="${a%/}"; done

real    0m0.018s
user    0m0.013s
sys     0m0.000s
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: Stränghantering i sh (eller i nödfall i bash)?

Inlägg av Johnny Rosenberg »

Konservburk skrev:Det som tar upp den mesta tiden där är fork:andet av dirname och basename. Använder du istället b="${a%/}" så lär det gå betydligt snabbare. Å andra sidan fungerar det då bara om det inte finns fler än ett / på slutet. Är man lite kreativ går den biten också att komma runt, iofs med risk för att det blir onödigt svårläst.

Kod: Markera allt

$ time for i in $(seq 1 1000); do b="$(dirname $a)/$(basename $a)"; done

real    0m1.787s
user    0m0.423s
sys     0m1.353s
$ time for i in $(seq 1 1000); do b="${a%/}"; done

real    0m0.018s
user    0m0.013s
sys     0m0.000s
Din maskin verkar vara drygt 5 gånger så snabb som min, för första exemplet är väl exakt samma som mitt? Bara det var ju imponerande. Nu är min bärbara kanske inte så där jätteimponerande: Dubbelkärna, 1,6 GHz, 2 GiB minne.

"${a%/}" kommer att fungera alldeles utmärkt i mitt fall, eftersom originalsträngen kommer ifrån Xdialog --dselect som ju alltid returnerar en sökväg med exakt en ”/” på slutet.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Skriv svar

Återgå till "Terminalforum"