Jag fick följande fel:
./assemblyDB.116.las test.sh: line 9: ${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"}: bad substitution och detta är skriptet:
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename no=${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"} echo $no done Kommentarer
- Vad försöker du åstadkomma med hängslen? Citera också dina variabler.
- Se Varför är looping över hitta ' s utgång dålig praxis?
Svar
 ${ ... } (lockiga hakparenteser) markerar flera sorter av  parameterutvidgning , varav det enklaste är att bara utvidga värdet på en variabel. Grejerna inom hängslen i din kod är inte ett giltigt parameternamn eller någon annan expansion, så skalet klagar. 
 Du verkar vilja byta kommando istället, för det är syntaxen $( ... ) (vanlig parentes). 
 Dessutom verkar ls i ls $filename | sed... onödigt expanderar variabeln till ditt filnamn och ls skickar bara igenom den. Du kan bara använda echo "$filename" | sed ... istället. 
Med detta sagt kan du göra dessa ändringar direkt i skalet:
no="${filename/assemblyDB.}" # remove first match no="${no/.las}" eller med standardoperatörerna:
no="${filename#assemblyDB.}" # remove from start of string no="${no%.las}" # remove from end of string  Om du kör sed kanske du vill notera att . matchar alla tecken i vanlig uttryck, så det skulle vara mer korrekt att citera det med en backslash. Du kan också ge en sed instans båda kommandona: sed -e "s/assemblyDB\.//" -e "s/\.las//". 
 Och sedan for filename in $(find . -type f -name "assemblyDB.*.las"); do har alla problem  parsing ls  har, mestadels det faktum att blanksteg och jokertecken i filnamn kommer att bryta det. I ksh / Bash / zsh kan du göra hela slingan i skalet: 
shopt -s globstar # in Bash for filename in **/assemblyDB.*.las; do ... Kommentarer
Svar
 I stället för ${} använd backticks ` [Knappen nedan Escape på tangentbordet.] 
Kommentarer
-  Vänligen don ' använd inte backticks. Använd kommandosubstitution. $( ... )
-  De är föråldrade, de är svåra att läsa, de <
t häckar och de kan alltid ersättas med parantesbyte. Dessutom är de svåra att placera i inbyggda kodblock på de flesta markdown-språk 🙂
echo `echo \`echo hello\`` . Ja, det behöver fly, men det betyder bara att ' inte är lika lätt att bo som $(...), inte att det ' är omöjligt. Svar
Kommandosubstitution (rad 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  motsvarar, som redan påpekats, (rad 3, ingen 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 eller kortare (rad 4 borta, nu ekar direkt)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//" | sed "s/.las//" done och kommandot sed kan reduceras till (rad 3)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//;s/.las//" done eller kanske extrahera den mellersta delen med sed: (still linje 3)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed -r "s/.*assemblyDB.(.*).las/\1/"" done hitta nu iterator istället för for-iterator: (rad 1 till 3, 4 borta)
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 Om dina filnamn finns i sådan eller liknande ordning kan följande också fungera:
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 (8 och 12 ingår, för att visa saknade filer i sekvensen).
<<<, har det troligen${var/pat/repl}. Om du kör sed kan du bara ge båda reglerna till ensedinstans:sed -e 's/assemblyDB\.//' -e 's/\.las//'