1. ホーム
  2. スクリプト・コラム
  3. リナックスシェル

Bashのトリック:変数を改行に割り当てる(ファイルが改行で終わっているかどうかを判断するため)

2022-02-09 06:20:22

改行に変数を割り当てる

bashでは、改行に変数を割り当てる場合、'˶'˶と書いてもダメで、'$'˶'と書く必要があるんです。例を挙げると、以下のようになります。

$ newline='\n'
$ echo $newline
\n
$ newline=$'\n'
$ echo $newline

newline変数に'n'を代入すると、nという文字列が得られ、newlineそのものは得られないことがわかります。

ここがbashとC言語と違うところです。
C言語では、'n'は改行文字そのものに対応し、1文字であるのに対し、"n"は文字列に対応する。
しかし、bashでは、'n'も文字列に対応する。

newline を $'ⅳn' に代入して、改行そのものを取得します。以下のような書き方は、man bashで確認してください。

<ブロッククオート

文字列'という形式の単語は特別に扱われます。この単語は文字列に展開され、バックスラッシュでエスケープされた文字がANSI Cで指定されているように置き換えられます。 バックスラッシュのエスケープシーケンスがある場合、以下のようにデコードされます。

 \n new line
 \r carriage return
 \t horizontal tab
 \' single quote

展開された結果は、ドル記号がなかったかのように、一重引用符で囲まれます。

つまり、$'string' は C のエスケープを使って対応する文字そのものを取得するように書くことができるのです。

ファイルの最終行が改行で終わっているかどうかを判定する

Linuxでは、以下のコマンドでファイルの最終行が改行で終わっているかどうかを判断することができます。

<ブロッククオート

test -n "$(tail filename -c 1)"

ここでは、tail filename -c 1 コマンドを使用して、ファイル名ファイルの最後の文字を取得しています。

実際には、filenameを判断したい具体的なファイル名に置き換える必要があります。

tailコマンドは、ファイルの終端を取得するコマンドです。cオプションで、ファイルの最後から何バイト取得するかを指定します。

cオプションの説明は、以下のようにman tailを参照してください。

-c, --bytes=K

または、-c +K で各ファイルの K 番目から始まるバイトを出力します。

つまり、tail -c 1 コマンドは、与えられたファイルの最後の文字を取得するように指定します。

ファイルの最後の文字を取得したら、その文字が改行文字であるかどうかを判断します。改行文字と同じかどうかを直接判断するのではなく、その文字がヌルであるかどうかを判断するのです。

これは、内部コマンドの出力を得るために $(tail filename -c 1) という置換コマンドを使用すると、bash が最後の改行文字を削除してしまうからです。

そのため、ファイルの最終行が改行で終わっている場合、$(tail filename -c 1) replacementコマンドは取得した改行を削除し、改行そのものを返さずにNULLの結果で終了してしまいます。

以下のようなコマンド置換の説明は、man bashを参照してください。

コマンド代替は、コマンドの出力をコマンド名に置き換えることができます。2つの形式があります。

  $(command)
 or
  `command`

Bash は command を実行し、コマンド置換をコマンドの標準出力に置き換えることで、展開を行います。

コマンド置換の後、末尾の改行が削除されていることがわかります。

というのは $(tail filename -c 1) コマンド置換では、末尾の改行文字が削除されます。 test -n で、最終的な結果が空文字列であるかどうかを判断します。

ファイルの最終行が改行で終わっている場合は $(tail filename -c 1) の結果はヌルです。 test -n コマンドを実行すると、1が返され、これは偽となります。

ファイルの最終行が改行で終わっていない場合は $(tail filename -c 1) が空でない場合、その結果は test -n コマンドは0を返しますが、これは真です。

に変更することができます。 test -z で判断します。ファイルの最終行が改行で終わっている場合は $(tail filename -c 1) が空であれば、その結果は test -z コマンドは0を返し、これは真である。

Bashのこの記事。ファイルの末尾が改行かどうかを判断するために、改行に変数を割り当てる」についての記事です。改行への変数の代入に関するより詳しい情報は、スクリプトハウスの過去の記事を検索するか、以下の記事を引き続きご覧になってください。