A következő hibát kaptam:
./assemblyDB.116.las test.sh: line 9: ${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"}: bad substitution
és ez a szkript:
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename no=${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"} echo $no done
megjegyzések
- Mit próbál elérni a fogszabályzóval? Idézd a változóidat is.
- Lásd: Miért hurkolja a ' keresés rossz gyakorlatot?
Válasz
${ ... }
(göndör zárójel) különféle paraméterbővítés , amelyek közül a legegyszerűbb csak egy változó értékének bővítése. A kódban a zárójelben lévő anyag nem érvényes paraméternév vagy bármilyen más kiterjesztés, ezért a shell panaszkodik.
Úgy tűnik, hogy inkább parancscserét szeretne, ezért a szintaxis $( ... )
(szokásos zárójel).
Ezenkívül a ls $filename | sed...
ls
is kissé látszik felesleges, a változó kibővül a fájlnévre, és a ls
csak átadja. Ehelyett használhatja a echo "$filename" | sed ...
-t.
Ez azt jelenti, hogy ezeket a módosításokat közvetlenül a shellben hajthatja végre:
no="${filename/assemblyDB.}" # remove first match no="${no/.las}"
vagy a szokásos operátorok használatával:
no="${filename#assemblyDB.}" # remove from start of string no="${no%.las}" # remove from end of string
Ha mégis futtatja a sed
fájlt, érdemes megjegyeznie, hogy a .
megfelel a rendszeres karaktereknek kifejezéseket, így helyesebb lenne visszavonással idézni. Azt is megadhatja az egyik sed
példányt, mindkét parancsot: sed -e "s/assemblyDB\.//" -e "s/\.las//"
.
És akkor for filename in $(find . -type f -name "assemblyDB.*.las"); do
minden kérdés elemzi az ls-t , főleg az a tény, hogy a fájlnevekben szereplő szóközök és helyettesítők betörik. A ksh / Bash / zsh fájlban megteheti az egész ciklust a shellben:
shopt -s globstar # in Bash for filename in **/assemblyDB.*.las; do ...
Megjegyzések
Válasz
A ${}
helyett használjon backticks `
[A billentyűzet alatt található Escape gomb.]
Megjegyzések
- Kérjük, ne ' nem használhat backtickeket. Használja a parancs behelyettesítését.
$( ... )
- Elavultak, nehezen olvashatók, nem fészkelnek ' és mindig helyébe zárójeles parancscsere lép. Ezenkívül nehéz őket beilleszteni az inline kódblokkokba a legtöbb jelölési nyelvnél 🙂
- Igen, ez így van. De ebben a kérdésben hol tévedtem a válaszom?
- Ön javasolta a backticks használatát.
- @Jesse_b Ott ' rengeteg olyan okok miatt, amelyek miatt nem használhat backticket, de nem tartozik ezek közé a képtelenség fészkelni őket:
echo `echo \`echo hello\``
. Igen, meg kell szöknie, de ez csak azt jelenti, hogy ' nem olyan könnyű fészkelni, mint$(...)
, és nem azt, hogy ' s lehetetlen.
Válasz
Parancscsere (3. sor)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename no=$(ls $filename | sed "s/assemblyDB.//" | sed "s/.las//") echo $no done
, amint arra már rámutattunk, egyenértékű (3. sor, nem 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
vagy rövidebb (a 4. sor elment, most közvetlenül visszhangzik)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//" | sed "s/.las//" done
és a sed parancs csökkenthető hogy (3. sor)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//;s/.las//" done
vagy esetleg kivonja a középső részt sed: (még mindig a 3. sor)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed -r "s/.*assemblyDB.(.*).las/\1/"" done
most find-iterator helyett for-iterator: (1-3. sor, 4 eltűnt)
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
Ha a fájlnevek vannak ilyen vagy hasonló sorrendben a következők is működhetnek:
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 és 12 is, a sorrendben hiányzó fájlok bemutatásához).
<<<
van, akkor valószínűleg${var/pat/repl}
is van. Ha mégis fut a sed, akkor mindkét szabályt megadhatja egysed
példánynak:sed -e 's/assemblyDB\.//' -e 's/\.las//'