Kan jag använda bash-variabelersättning för att extrahera en bit av en variabel baserat på en avgränsare? Jag försöker få det omedelbara katalognamnet på ett filnamn (i det här fallet foo
).
$ filename=./foo/bar/baz.xml
Jag vet att jag kunde göra något som
echo $filename | cut -d "/" -f 2
eller
echo $filename | awk -F "/" "{print $2}"
men det ” s blir långsam att gaffla awk
/ cut
för flera filnamn.
Jag gjorde en liten profilering av de olika lösningarna , med mina riktiga filer:
echo | klipp:
real 2m56.805s user 0m37.009s sys 1m26.067s
eko | awk:
real 2m56.282s user 0m38.157s sys 1m31.016s
@steeldrivers variabla substitution / skalparameterutvidgning:
real 0m0.660s user 0m0.421s sys 0m0.235s
@jai_s ”IFS-wrangling:
real 1m26.243s user 0m13.751s sys 0m28.969s
Båda förslagen var en enorm förbättring jämfört med mina befintliga idéer, men den variabla ersättningen är snabbast eftersom den inte kräver att nya processer släpps.
Kommentarer
- gnu.org/software/bash/manual / html_node / …
- Skicka alla filnamn till en anrop av awk och det blir betydligt snabbare än någon lösning i ren bash
- Kan du inte använda en matris, gör alla på en gång och placerar den i en ny matris?
Svar
Du kan ta bort den kortaste ledande strängen som matchar */
tmp="${filename#*/}"
och sedan ta bort den längsta efterföljande underlag som matchar /*
Svar
echo $f a/b/c $ (IFS="/";set $f; echo $1) a $ (IFS="/";set $f; echo $2) b $ (IFS="/";set $f; echo $3) c
med jokertecken som det verkar fungera med dubbla eller enkla citat –
f="a?b?c" $(IFS="?"; set $f; echo $1) a echo $f a*b*c (IFS="*"; set $f; echo $1) a
ja, du måste avaktivera IFS tillbaka till standard
unset IFS
Kommentarer
- Ooh, jag gillar det.
- Detta är vanligtvis min föredragna metod också, men kom ihåg att Bash stöder endast
$1
till$9
med denna syntax. För 10: e och senare argument måste${10}
-formuläret användas. - Fungerar inte ' t när
$f
innehåller jokertecken. Och du måste återställaIFS
efteråt (eller gör det i ett kommandosubstitution för att få värdet av ett fält och som avlägsnar efterföljande nya rader). - Exemplet fungerar isolerat (inuti Git bash på Windows), men när jag rör från find-kommandot får jag det här felet:
echo: write error: Bad address
. - Okej, ser ut som Jag måste
unset IFS
varje gång.
Svar
Feed listan till awk
för att påskynda den:
awk -F "/" "{print $2}" < <(find /usr) awk -F "/" "{print $2}" < inputfile
Demonstration:
time awk -F "/" "{print $2; SUM++} END {print "number of directories found: " SUM}" < <(find /usr -type d) usr usr . . number of directories found: 16748 real 0m8.910s user 0m0.050s sys 0m0.050s
Svar
Varför använder du inte kommandot” dirname ”istället för allt detta awk / sed / klippa saker?
filename=./foo/bar/baz.xml dirname $filename
Avkastning:
./foo/bar
Kommentarer
- I det här fallet letade jag efter den omedelbara katalogen, inte hela katalogvägen.