Kan jeg bruge bash-variabelerstatning til at udtrække et stykke af en variabel baseret på en delimeter? Jeg prøver at få det umiddelbare biblioteksnavn på et filnavn (i dette tilfælde foo
).
$ filename=./foo/bar/baz.xml
Jeg ved, at jeg kunne gøre noget som
echo $filename | cut -d "/" -f 2
eller
echo $filename | awk -F "/" "{print $2}"
men det ” s bliver langsom til at forkaste awk
/ cut
til flere filnavne.
Jeg lavede en lille profilering af de forskellige løsninger , ved hjælp af mine rigtige filer:
ekko | klip:
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 forslag var en enorm forbedring i forhold til mine eksisterende ideer, men den variable erstatning er hurtigst, fordi den ikke kræver forking af nye processer.
Kommentarer
- gnu.org/software/bash/manual / html_node / …
- Send alle filnavne til en påkaldelse af awk, og det vil være betydeligt hurtigere end nogen løsning i ren bash
- Kan du ikke bruge en matrix, skal du gøre dem alle på én gang og derefter placere den i en ny matrix?
Svar
Du kan fjerne det korteste ledende understreng, der matcher */
tmp="${filename#*/}"
og derefter fjerne den længste efterfølgende understreng, der matcher /*
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 wildcard det ser ud til at arbejde med dobbelt eller enkelt citater –
f="a?b?c" $(IFS="?"; set $f; echo $1) a echo $f a*b*c (IFS="*"; set $f; echo $1) a
ja, du bliver nødt til at frakoble IFS tilbage til standard
unset IFS
Kommentarer
- Ooh, det kan jeg godt lide.
- Dette er normalt også min foretrukne metode, men husk at Bash understøtter kun
$1
til$9
ved hjælp af denne syntaks. Til 10. og senere argumenter skal${10}
-formularen bruges. - Fungerer ikke ' t, når
$f
indeholder jokertegn. Og du skal gendanneIFS
bagefter (eller gør dette i en kommandosubstitution for at få værdien af et felt, og det fjerner efterfølgende nye linjer). - Eksemplet fungerer isoleret (inde i Git bash på Windows), men når jeg rører fra find-kommandoen, får jeg denne fejl:
echo: write error: Bad address
. - Okay, ligner Jeg skal
unset IFS
hver gang.
Svar
Feed listen til awk
for at fremskynde 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
Hvorfor bruger du ikke kommandoen” dirname “i stedet for alt dette awk / sed / klippe ting?
filename=./foo/bar/baz.xml dirname $filename
Udbytter:
./foo/bar
Kommentarer
- I dette tilfælde ledte jeg efter den øjeblikkelige bibliotek, ikke den fulde katalogsti.