Mohu použít substituci proměnné bash k extrahování části proměnné na základě delimetru? Snažím se získat okamžitý název adresáře názvu souboru (v tomto případě foo
).
$ filename=./foo/bar/baz.xml
Vím, že bych mohl udělat něco jako
echo $filename | cut -d "/" -f 2
nebo
echo $filename | awk -F "/" "{print $2}"
ale ono “ pomalu se rozvíjí awk
/ cut
pro více názvů souborů.
Udělal jsem trochu profilování různých řešení , pomocí mých skutečných souborů:
echo | cut:
real 2m56.805s user 0m37.009s sys 1m26.067s
echo | awk:
real 2m56.282s user 0m38.157s sys 1m31.016s
@steeldriver je variabilní substituce / rozšíření parametrů shellu:
real 0m0.660s user 0m0.421s sys 0m0.235s
@jai_s „s IFS-wrangling:
real 1m26.243s user 0m13.751s sys 0m28.969s
Oba návrhy byly velkým zlepšením oproti mým stávajícím nápadům, ale variabilní substituce je nejrychlejší, protože to nejde požadovat rozdvojení všech nových procesů.
Komentáře
- gnu.org/software/bash/manual / html_node / …
- Odeslat všechny názvy souborů na jedno vyvolání awk a bude to podstatně rychlejší než jakékoli řešení v čistém bash
- Nemůžete použít pole, proveďte všechny najednou a poté ho vložte do nového pole?
Odpovědět
Můžete odstranit nejkratší podřetězec, který odpovídá */
tmp="${filename#*/}"
a poté odstranit nejdelší koncový podřetězec, který odpovídá /*
Odpověď
echo $f a/b/c $ (IFS="/";set $f; echo $1) a $ (IFS="/";set $f; echo $2) b $ (IFS="/";set $f; echo $3) c
s divokou kartou se zdá, že funguje s dvojité nebo jednoduché uvozovky –
f="a?b?c" $(IFS="?"; set $f; echo $1) a echo $f a*b*c (IFS="*"; set $f; echo $1) a
ano, budete muset IFS znovu nastavit na výchozí
unset IFS
Komentáře
- Ó, to se mi líbí.
- Toto je také obvykle moje preferovaná metoda, ale mějte na paměti, že Bash pomocí této syntaxe podporuje pouze
$1
až$9
. U 10. a novějších argumentů musí být použit${10}
formulář. - ' nefunguje, když
$f
obsahuje zástupné znaky. A budete musetIFS
později obnovit (nebo to provést v substituci příkazu, abyste získali hodnotu pole a tím se odstranily koncové řádky). - Příklad funguje izolovaně (uvnitř Git bash v systému Windows), ale když přepojím z příkazu find, zobrazí se tato chyba:
echo: write error: Bad address
. - Dobře, vypadá to Musím
unset IFS
pokaždé.
Odpovědět
Feed seznam awk
pro urychlení:
awk -F "/" "{print $2}" < <(find /usr) awk -F "/" "{print $2}" < inputfile
Demonstrace:
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
Odpovědět
Proč nepoužíváte příkaz“ dirname „, místo toho všeho awk / sed / řezané věci?
filename=./foo/bar/baz.xml dirname $filename
Výnosy:
./foo/bar
Komentáře
- V tomto případě jsem hledal okamžitý adresář, nikoli úplnou cestu k adresáři.