Sain seuraavan virheen:
./assemblyDB.116.las test.sh: line 9: ${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"}: bad substitution
ja tämä on komentosarja:
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename no=${ls $filename | sed "s/assemblyDB.//" | sed "s/.las//"} echo $no done
kommentit
- Mitä yrität saavuttaa kannattimilla? Lainaa myös muuttujat.
- Katso Miksi etsintä etsi ' -lähtöä huonosti?
vastaus
${ ... }
(kiharat) merkitsee useita erilaisten -parametrilaajennus , joista yksinkertaisin on vain muuttujan arvon laajentaminen. Koodisi aaltosulkeissa olevat tavarat eivät ole kelvollisia parametrinimiä tai muita laajennuksia, joten komentotulkki valittaa.
Näyttää siltä, että haluat sen sijaan komentojen korvaamisen, joten syntaksin arvo on $( ... )
(tavallinen sulu).
Myös ls
kohdassa ls $filename | sed...
näyttää hieman turha, muuttuja laajenee tiedostosi nimeen ja ls
välittää sen vain. Voit käyttää vain echo "$filename" | sed ...
.
Tästä huolimatta voit tehdä nämä muutokset suoraan kuoressa:
no="${filename/assemblyDB.}" # remove first match no="${no/.las}"
tai käyttämällä vakio-operaattoreita:
no="${filename#assemblyDB.}" # remove from start of string no="${no%.las}" # remove from end of string
Jos suoritat sed
, kannattaa huomata, että .
vastaa mitä tahansa merkkiä tavallisessa lausekkeita, joten olisi oikeampi lainata sitä vinoviivalla. Voit myös antaa yhden sed
-esiintymän molemmat komennot: sed -e "s/assemblyDB\.//" -e "s/\.las//"
.
Ja sitten for filename in $(find . -type f -name "assemblyDB.*.las"); do
sisältää kaikki ongelmat, jotka jäsennetään ls : llä, lähinnä se, että tiedostonimessä olevat tyhjät välit ja jokerit rikkovat sen. Ksh / Bash / zsh-tiedostossa voit tehdä tuon kokonaisen silmukan kuoressa:
shopt -s globstar # in Bash for filename in **/assemblyDB.*.las; do ...
Kommentit
Vastaa
${}
käytä backticks `
[Esc-näppäimen alla oleva painike.]
Kommentit
- Älä ' t käytä backtickeja. Käytä komentojen korvaamista.
$( ... )
- ne ovat vanhentuneita, heitä on vaikea lukea, he eivät ' t pesää ja voivat aina korvataan suluilla komennon korvaaminen. Lisäksi niitä on vaikea sijoittaa inline-koodilohkoihin useimmilla markdown-kielillä 🙂
- Joo, se on totta. Mutta mistä vastauksestani meni pieleen tähän kysymykseen?
- Ehdotit backtickien käyttöä.
- @Jesse_b Siellä ' on paljon syistä olla käyttämättä backtickeja, mutta kyvyttömyys sijoittaa ne ei ole yksi niistä:
echo `echo \`echo hello\``
. Kyllä, se vaatii pakenemista, mutta se tarkoittaa vain sitä, että ' ei ole yhtä helppo pesiä kuin$(...)
, eikä sitä, että se ' on mahdotonta.
vastaus
Komennon korvaaminen (rivi 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
vastaa, kuten jo todettiin, (rivi 3, ei 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
tai lyhyempi (rivi 4 mennyt, nyt kaikuva suoraan)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//" | sed "s/.las//" done
ja sed -komentoa voidaan vähentää (rivi 3)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed "s/assemblyDB.//;s/.las//" done
tai ehkä pura keskiosa sedillä: (silti rivi 3)
for filename in $(find . -type f -name "assemblyDB.*.las"); do echo $filename echo $filename | sed -r "s/.*assemblyDB.(.*).las/\1/"" done
nyt find-iterator for-iteratorin sijaan: (rivit 1-3, 4 mennyt)
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
Jos tiedostonimet ovat tällainen tai vastaava järjestys, myös seuraava saattaa toimia:
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
(Mukana 8 ja 12, jotta voidaan näyttää puuttuvat tiedostot sarjasta).
<<<
, siinä on todennäköisesti myös${var/pat/repl}
. Jos suoritat sed-ohjelmaa, voit antaa molemmat säännöt yhdellesed
-esiintymälle:sed -e 's/assemblyDB\.//' -e 's/\.las//'