ファイルを読み、それを変数に保存したいのですが、ファイルを出力するだけでなく、変数を保持する必要があります。これどうやってするの?私はこのスクリプトを書きましたが、私が必要としていたものではありません。
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
私のスクリプトでは、ファイル名をパラメータとして指定できます。たとえば、ファイルに "aaaa"が含まれている場合は、次のように出力されます。
aaaa
11111-----
しかし、これは単にファイルを画面に表示するだけなので、それを変数に保存したいのです。これを行う簡単な方法はありますか?
クロスプラットフォームの最小公倍数sh
では、次のように使用します。
#!/bin/sh
value=`cat config.txt`
echo "$value"
bash
またはzsh
で、cat
を呼び出さずにファイル全体を変数に読み込むには、次のようにします。
#!/bin/bash
value=$(<config.txt)
echo "$value"
ファイルを丸呑みするためにcat
またはbash
でzsh
を呼び出すことは、 Catの無駄な使用 と見なされます。
改行を保存するためにコマンド置換を引用符で囲む必要はないことに注意してください。
Bash Hacker's Wiki - コマンド置換 - Specialties を参照してください。
ファイル全体を変数に読み込む場合は、次のようにします。
#!/bin/bash
value=`cat sources.xml`
echo $value
1行ずつ読みたい場合は、
while read line; do
echo $line
done < file.txt
2つの重要な落とし穴
これまでのところ他の答えでは無視されていました:
コマンド展開からの末尾の改行の削除
これは問題です。
value="$(cat config.txt)"
解決策を入力してください。ただし、read
ベースの解決策ではありません。
コマンド拡張は末尾の改行を削除します。
S="$(printf "a\n")"
printf "$S" | od -tx1
出力:
0000000 61
0000001
これはファイルから読み込む単純な方法を壊します。
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
POSIXの回避策:コマンド拡張に余分な文字を追加して後で削除します。
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
出力:
0000000 61 0a 0a
0000003
ほとんどのPOSIX回避策:ASCIIエンコード。下記参照。
NUL文字の削除
変数にNUL文字を格納するための正しいBash方法はありません 。
これは拡張とread
の両方の解決策に影響します、そして私はそれに対する良い回避策を知りません。
例:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
出力:
0000000 61 00 62
0000003
0000000 61 62
0000002
ハ、私たちのNULがなくなった!
回避策:
ASCIIエンコード下記参照。
bash拡張子$""
リテラルを使用してください。
S=$"a\0b"
printf "$S" | od -tx1
リテラルに対してのみ機能するので、ファイルからの読み取りには役立ちません。
落とし穴の回避策
ファイルのuuencode base64エンコードバージョンを変数に格納し、使用するたびにデコードします。
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
出力:
0000000 61 00 0a
0000003
uuencodeとudecodeは POSIX 7 ですが、デフォルトではUbuntu 12.04にはありません(sharutils
パッケージ)... bashプロセスの代わりのPOSIX 7代替の<()
置換拡張子は他のファイルに書き込む以外はありません...
もちろん、これは遅くて不便なので、本当の答えは、入力ファイルにNUL文字が含まれる可能性がある場合はBashを使用しないことです。
これは私のために働く:v=$(cat <file_path>) echo $v
As Ciro Santilli氏が としてコマンド置換を使用すると、末尾の改行が削除されます。末尾の文字を追加するという回避策は素晴らしいですが、しばらくの間それを使用した後、コマンド置換をまったく使用しない解決策が必要であると判断しました。
私のアプローチ は、stdinの内容を直接変数に読み込むために、read
組み込みの -v
フラグ と共にprintf
を使用するようになりました。
# 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"
}
これは末尾の改行の有無にかかわらず入力をサポートします。
使用例
$ read_input file_contents < /tmp/file
# $file_contents now contains the contents of /tmp/file