Bruker bash-variabelerstatning i stedet for cut / awk

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å gjenopprette IFS 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.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *