Pot folosi substituirea variabilei bash pentru a extrage o bucată dintr-o variabilă pe baza unui delimitator? Încerc să obțin numele directorului imediat al unui nume de fișier (în acest caz, foo
).
$ filename=./foo/bar/baz.xml
Știu că aș putea face ceva de genul
echo $filename | cut -d "/" -f 2
sau
echo $filename | awk -F "/" "{print $2}"
dar ” Se încetinește să bifurcați awk
/ cut
pentru mai multe nume de fișiere.
Am făcut un mic profil al diferitelor soluții , folosind fișierele mele reale:
echo | cut:
real 2m56.805s user 0m37.009s sys 1m26.067s
echo | awk:
real 2m56.282s user 0m38.157s sys 1m31.016s
@steeldriver „s variație variabilă / expansiune parametru shell:
real 0m0.660s user 0m0.421s sys 0m0.235s
@jai_s „s IFS-wrangling:
real 1m26.243s user 0m13.751s sys 0m28.969s
Ambele sugestii au fost o îmbunătățire imensă față de ideile mele existente, dar substituția variabilă este cea mai rapidă, deoarece nu” t necesită falsificarea oricăror procese noi.
Comentarii
- gnu.org/software/bash/manual / html_node / …
- Trimiteți toate numele fișierelor către o invocare de awk și va fi semnificativ mai rapid decât orice soluție în bash pur
- Nu puteți utiliza o matrice, le faceți simultan, apoi puneți-o într-o matrice nouă?
Răspuns
Puteți elimina cel mai scurt substring care se potrivește cu */
tmp="${filename#*/}"
și apoi puteți elimina cel mai lung substring final care se potrivește cu /*
Răspuns
echo $f a/b/c $ (IFS="/";set $f; echo $1) a $ (IFS="/";set $f; echo $2) b $ (IFS="/";set $f; echo $3) c
cu wild card cu care pare să funcționeze ghilimele duble sau simple –
f="a?b?c" $(IFS="?"; set $f; echo $1) a echo $f a*b*c (IFS="*"; set $f; echo $1) a
da, va trebui să anulați IFS-ul la valorile implicite
unset IFS
Comentarii
- Ooh, îmi place asta.
- De obicei, aceasta este și metoda mea preferată, dar rețineți că Bash acceptă numai
$1
prin$9
utilizând această sintaxă. Pentru argumentele 10 și ulterioare, trebuie utilizat formularul${10}
. - Nu funcționează ' când
$f
conține metacaractere. Și trebuie să restaurațiIFS
după aceea (sau faceți acest lucru într-o înlocuire a comenzilor, pentru a obține valoarea unui câmp și care elimină liniile noi). - Exemplul funcționează izolat (în interiorul Git bash pe Windows), dar când trec din comanda find, primesc această eroare:
echo: write error: Bad address
. - Bine, arată ca Trebuie să
unset IFS
de fiecare dată.
Răspunde
Feed lista către awk
pentru ao accelera:
awk -F "/" "{print $2}" < <(find /usr) awk -F "/" "{print $2}" < inputfile
Demonstrație:
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
Răspunde
De ce nu folosești comanda” dirname „, în loc de toate acestea awk / sed / lucruri tăiate?
filename=./foo/bar/baz.xml dirname $filename
Randamente:
./foo/bar
Comentarii
- În acest caz, am căutat directorul imediat, nu calea completă a directorului.