Saya ingin membaca file dan menyimpannya dalam variabel, tetapi saya perlu menyimpan variabel dan tidak hanya mencetak file. Bagaimana saya bisa melakukan ini? Saya telah menulis skrip ini tetapi itu tidak cukup yang saya butuhkan:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
Dalam skrip saya, saya dapat memberikan nama file sebagai parameter, jadi, jika file tersebut berisi "aaaa", misalnya, itu akan mencetak ini:
aaaa
11111-----
Tapi ini hanya mencetak file ke layar, dan saya ingin menyimpannya ke dalam variabel! Apakah ada cara mudah untuk melakukan ini?
cat
atau$(<someFile)
akan menghasilkan output yang tidak lengkap (ukurannya lebih kecil dari file sebenarnya).Jawaban:
Di lintas platform, penyebut terendah yang
sh
Anda gunakan:Di
bash
atauzsh
, untuk membaca seluruh file menjadi variabel tanpa memohoncat
:Meminjam
cat
dibash
atauzsh
untuk mencucup file akan dianggap sebagai Useless Penggunaan Cat .Perhatikan bahwa tidak perlu mengutip substitusi perintah untuk mempertahankan baris baru.
Lihat: Wiki Bash Hacker - substitusi perintah - Spesialisasi .
sumber
value="`cat config.txt`"
danvalue="$(<config.txt)"
lebih aman jika config.txt berisi spasi?cat
seperti di atas tidak selalu dianggap sebagai penggunaan yang tidak bergunacat
. Misalnya,< invalid-file 2>/dev/null
akan menghasilkan pesan kesalahan yang tidak dapat dialihkan ke/dev/null
, sedangkancat invalid-file 2>/dev/null
mendapatkan dialihkan dengan benar/dev/null
.value=$(<config.txt)
bagus, tetapivalue = $(<config.txt)
buruk. Hati-hati dengan ruang itu.Jika Anda ingin membaca seluruh file menjadi variabel:
Jika Anda ingin membacanya baris demi baris:
sumber
echo "$value"
. Jika tidak, shell akan melakukan tokenization dan ekspansi wildcard pada nilai.read -r
bukan hanyaread
- selalu, kecuali jika Anda secara khusus memerlukan perilaku warisan aneh yang Anda singgung.Dua perangkap penting
yang diabaikan oleh jawaban lain sejauh ini:
Mengikuti penghapusan baris baru dari ekspansi perintah
Ini adalah masalah untuk:
ketik solusi, tetapi tidak untuk
read
solusi berbasis.Ekspansi perintah menghapus trailing newlines:
Output:
Ini memecah metode naif membaca dari file:
Solusi POSIX: tambahkan char tambahan ke perintah ekspansi dan hapus nanti:
Output:
Solusi Hampir POSIX: ASCII encode. Lihat di bawah.
Penghapusan karakter NUL
Tidak ada cara Bash yang waras untuk menyimpan karakter NUL dalam variabel .
Ini memengaruhi ekspansi dan
read
solusi, dan saya tidak tahu solusi yang bagus untuk itu.Contoh:
Output:
Ha, NUL kita hilang!
Penanganan masalah:
Encode ASCII. Lihat di bawah.
gunakan bash extension
$""
literals:Hanya berfungsi untuk literal, jadi tidak berguna untuk membaca dari file.
Solusi untuk perangkap
Menyimpan versi yang disandikan uuencode base64 dari file dalam variabel, dan mendekode sebelum setiap penggunaan:
Keluaran:
uuencode dan udecode adalah POSIX 7 tetapi tidak di Ubuntu 12.04 secara default (
sharutils
paket) ... Saya tidak melihat alternatif POSIX 7 untuk proses bash<()
ekstensi pengganti kecuali menulis ke file lain ...Tentu saja, ini lambat dan tidak nyaman, jadi saya kira jawaban sebenarnya adalah: jangan gunakan Bash jika file input mungkin berisi karakter NUL.
sumber
S="$(printf "\\\'\"")"; echo $S
. Output:\'"
. Jadi itu berfungsi =)$()
ekspansi, contoh saya menunjukkan bahwa$()
ekspansi bekerja dengan baik\'"
.ini bekerja untuk saya:
v=$(cat <file_path>) echo $v
sumber
Seperti yang dicatat Ciro Santilli menggunakan pergantian perintah akan meninggalkan baris baru. Solusi mereka menambahkan karakter tambahan sangat bagus, tetapi setelah menggunakannya cukup lama saya memutuskan saya membutuhkan solusi yang tidak menggunakan substitusi perintah sama sekali.
Pendekatan saya sekarang menggunakan
read
bersama denganprintf
builtin ini-v
bendera untuk membaca isi stdin langsung ke variabel.Ini mendukung input dengan atau tanpa mengikuti baris baru.
Contoh penggunaan:
sumber
_contents="${_contents}${_line}\n "
mempertahankan baris baru?$'\n'
? Itu perlu, kalau tidak Anda menambahkan literal\
dann
karakter. Blok kode Anda juga memiliki ruang ekstra di bagian akhir, tidak yakin apakah itu disengaja, tapi itu akan membuat setiap baris berikutnya dengan spasi kosong.Anda dapat mengakses 1 baris sekaligus untuk loop
Salin seluruh konten ke File (say line.sh); Menjalankan
sumber
for
lingkaran tidak loop melalui saluran, itu loop atas kata-kata. Dalam kasus/etc/passwd
, setiap baris hanya berisi satu kata. Namun, file lain mungkin berisi banyak kata per baris.