「read」がファイル全体を一度に読み取れるように、「read」の「区切り文字」として機能する文字がありますか?

「read」がファイル全体を一度に読み取れるように、「read」の「区切り文字」として機能する文字がありますか?

Bashマニュアルのread組み込みコマンドについて

-d delimの最初の文字は、delim改行文字ではなく入力行を終了するために使用されます。

(文字であるEOFと一致しない限り)、一致せずに常にファイル全体を一度に読み取るようにdelim文字を指定できますか?readread

ありがとうございます。

答え1

bashとにかく変数にNULバイトを格納できないため、いつでも次のことができます。

IFS= read -rd '' var < file

ファイルにNULバイトがない場合、最初のNULバイトまたはファイルの終わりまでファイルの内容を保存します(定義によるテキストファイル(少なくともPOSIX定義による)はNULバイトを含みません)。

別のオプションは、ファイルの内容を行配列(行区切り文字を含む)として保存することです。

readarray array < file

その後、次のことで参加できます。

IFS=; var="${array[*]}"

入力に ​​NUL バイトが含まれていると、各行の最初の項目以降のすべての項目が失われます。

POSIX sh構文では、次のことができます。

var=$(cat < file; echo .); var=${var%.}

我々は、.コマンド置換がすべての末尾の改行を削除するという事実を説明するために1つを追加してから削除しました。

ファイルにNULバイトが含まれている場合、動作は実装ごとに異なります。zshこれを保持する唯一のシェルです(また、変数にNULバイトを格納できる唯一のシェルでもあります)。bash一部の他のシェルはそれを削除し、他のシェルはそれをブロックし、最初のNULが発生した後にすべてを破棄します。

次のように、いくつかのエンコーディングでファイルの内容を保存することもできます。

var=$(uuencode -m - < file)

次の方法で再インポートします。

printf '%s\n' "$var" | uudecode

または、パラメータで使用\0000できるようにNULでエンコードします(文字セットBIG5、GB18030、GBK、BIG5-HKCSCのロケールを使用しないと仮定)。printf %bbash

var=; while true; do
  if IFS= read -rd '' rec; then
    var+=${rec//\\/\\\\}\\0000
  else
    var+=${rec//\\/\\\\}
    break
  fi
done < file

それから:

printf %b "$var"

再インポート。

答え2

答えは一般的に「いいえ」です。これは通常、ファイルの終わりを示す実際の文字がファイルにないためです。

ここで提案されているような他のアプローチを試してみることをお勧めします。https://stackoverflow.com/questions/10984432/how-to-read-the-file-content-into-a-variable-in-one-go。使用:

IFS="" contents=$(<file)

特にエレガントです。 Bashはの内容をfile変数として読み込みcontentsますが、Bash変数はNULLバイトを保持できません(CスタイルのNULLバイトで終わる文字列の内部使用のため)。IFS=""単語の区切りを無効にするには、内部フィールド区切り文字を空白のままにします(したがって改行文字の削除を防ぎます)。

注:(評判ポイントが不足しているため)readこの-Nオプションの使用を提案する回答については言及できないため、この回答は定義に従ってファイルサイズがわからないため、現状のまま動作することは保証されません。事前に。

答え3

では、(文字数)オプションをbash使用します。-N

read -rN 40000000 foo

-rファイルにバックスラッシュエスケープ文字を含めるには、このオプションを無視します。

からhelp read

-N nchars return only after reading exactly NCHARS characters, unless
   EOF is encountered or read times out, ignoring any delimiter

EOF非文字状態:a read(シェル組み込みではなくシステムコール)がゼロ長を返しました。ただし、他の関数は、すべての文字セットの有効な文字と競合することができない(-1)値の整数をgetchar()便利に返します。したがって、EOF以前のオペレーティングシステムによっては、ファイルシステムメタデータの全ブロックのみが追跡されるため、EOFマーカー(通常は)を使用するという^Z事実によって混乱がより重み付けられます。

奇妙なことに、read -N0「遅いフルルック音」を出すようです(ファイル全体を同じ方法で読みますが、各文字に対してシステムコールを実行します)。意図した機能なのかはよくわかりません;-)

strace -fe trace=read ./bash -c 'echo yes | read -N0'
...
[pid  8032] read(0, "y", 1)             = 1
[pid  8032] read(0, "e", 1)             = 1
[pid  8032] read(0, "s", 1)             = 1
[pid  8032] read(0, "\n", 1)            = 1
[pid  8032] read(0, "", 1)              = 0

bash組み込みで使用するバッファはread128バイトにすぎず、大容量ファイルを読み取るために使用しないでください。また、ファイルがutf-8を多用する場合はそれを使用する必要がありますLC_CTYPE=C read ...。それ以外の場合は、bash128バイトの読み取りとバイト単位の読み取りが交互に行われるため、速度が遅くなります。

関連情報