Saya ingin membaca sebuah file dan menyimpannya dalam variabel, tetapi saya perlu untuk menjaga variabel dan bukan hanya mencetak file. Bagaimana saya bisa melakukan ini? Saya telah menulis script ini, tapi itu bukan't cukup apa yang saya butuhkan:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
Dalam naskah saya, saya bisa memberikan nama file sebagai parameter, jadi, jika file 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 hal ini?
Dalam cross-platform, terendah-umum-penyebut sh
yang anda gunakan:
#!/bin/sh
value=`cat config.txt`
echo "$value"
Di bash
atau zsh
, untuk membaca seluruh file ke dalam sebuah variabel tanpa melibatkan kucing
:
#!/bin/bash
value=$(<config.txt)
echo "$value"
Menerapkan kucing
di bash
atau zsh
untuk slurp file akan dianggap sia-Sia Penggunaan Cat.
Perhatikan bahwa hal ini tidak perlu untuk mengutip perintah substitusi untuk melestarikan baris baru.
Lihat: Bash Hacker's Wiki - Perintah substitusi - Spesialisasi.
Dua penting perangkap
yang diabaikan oleh jawaban yang lain sejauh ini:
Baris baru mengikuti penghapusan dari perintah ekspansi
Ini adalah masalah untuk:
value="$(cat config.txt)"
jenis solusi, tapi tidak untuk membaca
berbasis solusi.
Perintah ekspansi menghilangkan tertinggal baris baru:
S="$(printf "a\n")"
printf "$S" | od -tx1
Output:
0000000 61
0000001
Ini istirahat naif metode membaca dari file:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
POSIX solusi: tambahkan ekstra char perintah ekspansi dan menghapusnya nanti:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Output:
0000000 61 0a 0a
0000003
Hampir POSIX solusi: ASCII encode. Lihat di bawah ini.
Karakter NUL penghapusan
Tidak waras Bash cara untuk menyimpan NUL karakter di variables.
Hal ini mempengaruhi perluasan dan membaca
solusi, dan saya don't tahu apa solusi untuk itu.
Contoh:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Output:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ha, kami NUL hilang!
Penyelesaian:
ASCII encode. Lihat di bawah ini.
menggunakan bash ekstensi $","
literal:
S=$"\0b" printf "$S" | od -tx1
Hanya bekerja untuk literal, jadi tidak berguna untuk membaca dari file.
Solusi untuk perangkap
Toko yang uuencode base64 encoded versi dari file dalam variabel, dan decode sebelum setiap penggunaan:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
Output:
0000000 61 00 0a
0000003
uuencode dan udecode adalah POSIX 7 tapi tidak di Ubuntu 12.04 secara default (sharutils
paket)... saya don't melihat POSIX 7 alternatif untuk bash proses <()
substitusi ekstensi kecuali menulis ke file lain...
Tentu saja, ini adalah lambat dan tidak nyaman, jadi saya kira jawaban yang benar adalah: don't menggunakan Bash jika input file dapat berisi karakter NUL.
Sebagai Ciro Santilli catatan menggunakan perintah substitusi akan turun mengikuti baris. Mereka menyiasatinya dengan menambahkan karakter sangat bagus, tapi setelah menggunakannya untuk beberapa waktu saya memutuskan saya membutuhkan solusi yang tidak't menggunakan perintah substitusi sama sekali.
Pendekatan sekarang menggunakan baca
bersama dengan printf
builtin's -v
flag dalam rangka untuk membaca isi dari stdin langsung ke sebuah variabel.
# Reads stdin into a variable, accounting for trailing newlines. Avoids needing a subshell or
# command substitution.
read_input() {
# Use unusual variable names to avoid colliding with a variable name
# the user might pass in (notably "contents")
: "${1:?Must provide a variable to read into}"
if [[ "$1" == '_line' || "$1" == '_contents' ]]; then
echo "Cannot store contents to $1, use a different name." >&2
return 1
fi
local _line _contents
while read -r _line; do
_contents="${_contents}${_line}"$'\n'
done
_contents="${_contents}${_line}" # capture any content after the last newline
printf -v "$1" '%s' "$_contents"
}
Ini mendukung input dengan atau tanpa mengikuti baris.
Contoh penggunaan:
$ read_input file_contents < /tmp/file
# $file_contents now contains the contents of /tmp/file
Anda dapat mengakses 1 baris pada satu waktu untuk loop
#!/bin/bash -eu
#This script prints contents of /etc/passwd line by line
FILENAME='/etc/passwd'
I=0
for LN in $(cat $FILENAME)
do
echo "Line number $((I++)) --> $LN"
done
Copy seluruh isi File (mengatakan line.sh ) ; Melaksanakan
chmod +x line.sh ./line.sh