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
- Co se snažíte dosáhnout pomocí rovnátek? Citujte také své proměnné.
- Viz Proč je smyčka přes find ' s výstupem špatná praxe?
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
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í).
<<<, má pravděpodobně také${var/pat/repl}. Pokud spustíte sed, můžete obě pravidla dát jednésedinstanci:sed -e 's/assemblyDB\.//' -e 's/\.las//'