$ {ls … | futó rossz helyettesítés sed …} a bash

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

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

  • @Jesse_b, igen, de ha a héjad <<< van, akkor valószínűleg ${var/pat/repl} is van. Ha mégis fut a sed, akkor mindkét szabályt megadhatja egy sed példánynak: sed -e 's/assemblyDB\.//' -e 's/\.las//'
  • Csak szerette volna rámutat az UUOE-ra;)

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).

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük