špatná substituce běží $ {ls … | sed …} s bash

Zobrazila se následující chyba:

./assemblyDB.116.las test.sh: line 9: ${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"}: bad substitution 

a toto je skript:

for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename no=${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"} echo $no done 

Komentáře

Odpověď

${ ... } (složené závorky) označuje několik druhy rozšiřování parametrů , nejjednodušší je pouze rozšíření hodnoty proměnné. Obsah uvnitř složených závorek ve vašem kódu není platný název parametru nebo jiné rozšíření, takže si shell stěžuje.

Zdá se, že místo toho chcete nahradit příkaz, proto je syntaxe $( ... ) (běžná závorka).

Také ls v ls $filename | sed... vypadá trochu zbytečné, proměnná se rozšíří na váš název souboru a ls ji pouze předá. Místo toho můžete použít echo "$filename" | sed ....

To znamená, že tyto úpravy můžete provést přímo v shellu:

no="${filename/assemblyDB.}" # remove first match no="${no/.las}" 

nebo pomocí standardních operátorů:

no="${filename#assemblyDB.}" # remove from start of string no="${no%.las}" # remove from end of string 

Pokud spustíte sed, můžete si všimnout, že . odpovídá jakémukoli znaku v regulárním výrazy, takže by bylo správnější citovat to zpětným lomítkem. Můžete také dát jedné sed instanci oba příkazy: sed -e "s/assemblyDB\.//" -e "s/\.las//".

A pak for filename in $(find . -type f -name "assemblyDB.*.las"); do má všechny problémy parsování ls má, hlavně to, že mezery a zástupné znaky v názvech souborů to rozbijí. V ksh / Bash / zsh můžete udělat celou smyčku v shellu:

shopt -s globstar # in Bash for filename in **/assemblyDB.*.las; do ... 

Komentáře

  • @Jesse_b, ano, ale pokud má váš shell <<<, má pravděpodobně také ${var/pat/repl}. Pokud spustíte sed, můžete obě pravidla dát jedné sed instanci: sed -e 's/assemblyDB\.//' -e 's/\.las//'
  • Jen jsem chtěl poukázat na UUOE;)

odpověď

místo ${} použijte backticks ` [Tlačítko pod klávesou Escape na vaší klávesnici.]

Komentáře

  • Prosím ' nepoužívejte zpětné lístky. Použijte substituci příkazu. $( ... )
  • Jsou zastaralé, těžko čitelné, ' se nehnízdí a nemohou vždy být nahrazen nahrazením příkazu v závorkách. Navíc je těžké je umístit do vložených bloků kódu ve většině značkovacích jazyků 🙂
  • Ano, je to tak. Ale pokud jde o tuto otázku, kde se moje odpověď pokazila?
  • Navrhli jste použít zpětné odkazy.
  • @Jesse_b Existuje ' spousta důvodů, proč nepoužívat zpětné lístky, ale neschopnost je vnořit není jedním z nich: echo `echo \`echo hello\`` . Ano, vyžaduje to únik, ale to prostě znamená, že ' není tak snadné vnořit jako $(...), ne to, že ' je nemožné.

Odpovědět

Náhrada příkazů (řádek 3)

for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename no=$(ls $filename | sed "s/assemblyDB.//" | sed "s/.las//") echo $no done 

je ekvivalentní, jak již bylo uvedeno, (řádek 3, žádný ls)

for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename no=$(echo $filename | sed "s/assemblyDB.//" | sed "s/.las//") echo $no done 

nebo kratší (řádek 4 zmizel, nyní se ozývá přímo)

for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//" | sed "s/.las//" done 

a příkaz sed lze snížit do (řádek 3)

for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//;s/.las//" done 

nebo možná extrahujte střední část pomocí sed: (stále řádek 3)

for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed -r "s/.*assemblyDB.(.*).las/\1/"" done 

nyní find-iterator místo for-iterator: (řádek 1 až 3, 4 pryč)

find . -type f -name "assemblyDB.*.las" -printf "%f\n" -exec sh -c " echo {} | sed -r "s/.*assemblyDB.(.*).las/\1/"" ";" assemblyDB.11.las 11 assemblyDB.9.las 9 assemblyDB.10.las 10 

Pokud jsou vaše názvy souborů v takové nebo podobné pořadí, může fungovat i následující:

for i in {8..12} ; do ls assemblyDB.$i.las && echo $i ; done 2>/dev/null assemblyDB.9.las 9 assemblyDB.10.las 10 assemblyDB.11.las 11 

(včetně 8 a 12, aby se ukázaly chybějící soubory v pořadí).

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *