ファイルを読み込んで変数に保存したいのですが、単にファイルをプリントアウトするのではなく、変数を保持する必要があります。 どうすればいいのでしょうか?このスクリプトは書きましたが、私が必要としているものとは全く違います。
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
私のスクリプトでは、パラメータとしてファイル名を与えることができるので、例えば、ファイルに"aaa"が含まれている場合は、次のように出力されます。
aaaa
11111-----
しかし、これではファイルを画面に出力するだけで、それを変数に保存したいのです! 簡単にできる方法はありますか?
クロスプラットフォームでは、最小公倍数の sh
を使います。
#!/bin/sh
value=`cat config.txt`
echo "$value"
bashや
zshでは、
cat` を起動せずに、ファイル全体を変数に読み込むことができます。
#!/bin/bash
value=$(<config.txt)
echo "$value"
bash
や zsh
で cat
を起動してファイルを読み込むことは Useless Use of Cat とみなされます。
なお、改行を保持するためにコマンド置換を引用する必要はありません。
参照してください。Bash Hacker's Wiki - Command substitution - Specialitiesを参照してください。
2つの重要な落とし穴。
は、これまでの他の回答では無視されていました。
1.コマンド展開時の末尾の改行除去 1.NUL文字の除去
**コマンド展開時の改行の除去
という問題があります。
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 を使わない」ということだと思います。