Kan jeg bruke bash-variabelerstatning for å trekke ut et stykke av en variabel basert på en delimeter? Jeg prøver å få det umiddelbare katalognavnet til et filnavn (i dette tilfellet foo
).
$ filename=./foo/bar/baz.xml
Jeg vet at jeg kunne gjøre noe sånt som
echo $filename | cut -d "/" -f 2
eller
echo $filename | awk -F "/" "{print $2}"
men det » s blir sakte å forkaste awk
/ cut
for flere filnavn.
Jeg gjorde en liten profilering av de forskjellige løsningene , ved hjelp av de virkelige filene mine:
ekko | klipp:
real 2m56.805s user 0m37.009s sys 1m26.067s
ekko | awk:
real 2m56.282s user 0m38.157s sys 1m31.016s
@steeldrivers variable substitution / shell parameter expansion:
real 0m0.660s user 0m0.421s sys 0m0.235s
@jai_s «IFS-wrangling:
real 1m26.243s user 0m13.751s sys 0m28.969s
Begge forslagene var en enorm forbedring i forhold til mine eksisterende ideer, men den variable erstatningen er raskest fordi den ikke krever forking av nye prosesser.
Kommentarer
- gnu.org/software/bash/manual / html_node / …
- Send alle filnavnene til en påkalling av awk, og det vil være betydelig raskere enn noen løsning i ren bash
- Kan du ikke bruke en matrise, kan du gjøre alt på en gang og deretter sette den i en ny matrise?
Svar
Du kan fjerne den korteste ledende understrengen som samsvarer med */
tmp="${filename#*/}"
og deretter fjerne den lengste etterfølgende understreng som samsvarer med /*
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 jokertegn det ser ut til å fungere med doble eller enkle anførselstegn –
f="a?b?c" $(IFS="?"; set $f; echo $1) a echo $f a*b*c (IFS="*"; set $f; echo $1) a
ja, du må deaktivere IFS tilbake til standard
unset IFS
Kommentarer
- Ooh, jeg liker det.
- Dette er vanligvis også min foretrukne metode, men husk at Bash støtter bare
$1
til$9
ved hjelp av denne syntaksen. For tiende og senere argumenter må${10}
-skjemaet brukes. - Fungerer ikke ' t når
$f
inneholder jokertegn. Og du må gjenoppretteIFS
etterpå (eller gjør dette i en kommandosubstitusjon, for å få verdien av et felt, og som fjerner etterfølgende nye linjer). - Eksemplet fungerer isolert (inne i Git bash på Windows), men når jeg piper fra finn-kommandoen får jeg denne feilen:
echo: write error: Bad address
. - Ok, ser ut som Jeg må
unset IFS
hver gang.
Svar
Feed listen til awk
for å øke hastigheten:
awk -F "/" "{print $2}" < <(find /usr) awk -F "/" "{print $2}" < inputfile
Demonstrasjon:
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
Hvorfor ikke bruke kommandoen» dirname «i stedet for alt dette awk / sed / klippe ting?
filename=./foo/bar/baz.xml dirname $filename
Utbytter:
./foo/bar
Kommentarer
- I dette tilfellet lette jeg etter den umiddelbare katalogen, ikke hele katalogbanen.