Folosind substituirea variabilei bash în loc de cut / awk

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ți IFS 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.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *