Haluan lukea tiedoston ja tallentaa sen muuttujaan, mutta minun on säilytettävä muuttuja eikä vain tulostettava tiedosto. Miten voin tehdä tämän? Olen kirjoittanut tämän skriptin, mutta se ei ole aivan sitä, mitä tarvitsin:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
Skriptissäni voin antaa tiedoston nimen parametrina, joten jos tiedosto sisältää esimerkiksi "aaaa", se tulostaisi tämän:
aaaa
11111-----
Mutta tämä vain tulostaa tiedoston näytölle, ja haluan tallentaa sen muuttujaan! Onko olemassa helppoa tapaa tehdä tämä?
Ristikkäisalustaisessa, pienimmän yhteisen nimittäjän sh
:ssä käytät:
#!/bin/sh
value=`cat config.txt`
echo "$value"
bashissa
tai zsh
:ssä koko tiedoston lukemiseen muuttujaan kutsumatta cat
:ia:
#!/bin/bash
value=$(<config.txt)
echo "$value"
cat
:n kutsuminen bash
:ssa tai zsh
:ssa tiedoston läträämiseksi olisi Useless Use of Cat.
Huomaa, että komennon korvaavaa komentoa ei tarvitse lainata uusien rivien säilyttämiseksi.
Ks: Bash Hacker's Wiki - Komennon korvaaminen - Erikoisuudet.
Kaksi tärkeää sudenkuoppaa
jotka on jätetty huomiotta muissa vastauksissa tähän mennessä:
Trailing newline poisto komentojen laajennuksesta
Tämä on ongelma:
value="$(cat config.txt)"
tyyppisille ratkaisuille, mutta ei read
-pohjaisille ratkaisuille.
Komentojen laajentaminen poistaa perässä olevat rivinvaihdot:
S="$(printf "a\n")"
printf "$S" | od -tx1
Tulokset:
0000000 61
0000001
Tämä rikkoo naiivin tavan lukea tiedostoista:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
POSIX-ratkaisu: liitä ylimääräinen merkki komentolaajennukseen ja poista se myöhemmin:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Tulokset:
0000000 61 0a 0a
0000003
Lähes POSIX-ratkaisu: ASCII-koodaus. Katso alla.
NUL-merkin poistaminen
Ei ole mitään järkevää Bash-tapaa tallentaa NUL-merkkejä muuttujiin.
Tämä vaikuttaa sekä laajennus- että read
-ratkaisuihin, enkä tiedä mitään hyvää ratkaisua siihen.
Esimerkki:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Tulokset:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ha, meidän NUL on poissa!
Ratkaisut:
ASCII-koodaus. Katso alla.
Käytä bashin laajennuksen $""
kirjaimia:
S=$"a\0b"
printf "$S" | od -tx1
Toimii vain literaaleille, joten siitä ei ole hyötyä tiedostojen lukemisessa.
Työkaluratkaisu sudenkuoppia varten
Tallenna muuttujaan uuencode base64-koodattu versio tiedostosta ja purkaa se ennen jokaista käyttökertaa:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
Tulos: - Kertokaa, että kaikki tiedostot on käännetty ja että ne on käännetty..:
0000000 61 00 0a
0000003
uuencode ja udecode ovat POSIX 7, mutta eivät ole oletuksena Ubuntu 12.04:ssä (sharutils
-paketti)... En näe POSIX 7 -vaihtoehtoa bash-prosessin <()
-korvauslaajennukselle paitsi kirjoittamalla toiseen tiedostoon...
Tämä on tietysti hidasta ja hankalaa, joten todellinen vastaus lienee: älä käytä Bashia, jos syötetiedosto voi sisältää NUL-merkkejä.