コピペ可|bash/while read lineで行単位で処理:5パターン

シェル/bash

こんにちは。

普段はIT業界についてのブログを執筆してるエンジニアです。
» 参考:プログラマーの年収は200万円以下です【IT業界の残酷な成功法則】
» 参考:【一生使える本です】bashの解説書 厳選3選【おすすめ】

今回は、bashについての解説記事です。

bashのwhile read lineについて調べる人

bashのwhile read lineについて調べる人
「bashでwhile read lineを使うと1行ずつ入力を読み込めて便利だったと思うのですが、書き方を忘れました。正しい書き方はどのようにすればいいでしょう?コピペで利用可能な例が見たいです。」

こんな疑問を解決します。

本記事の内容

この記事を書いている私はIT業界歴12年、年収1,000万円ちょっとの金融系エンジニアです。IRIXやSolarisなどのUnixやCygwin、mac、Linuxなど様々な環境でbashによるスクリプティングを行ってきました。

bashは極めて簡単なプログラミング言語ですが、空白の有無などで構文エラーとなること、javaなど一般的なプログラミング言語に慣れている方にとっては直感的ではない構文であることから、忘れてしまうことも多いかと思います。そのため、bashのwhile read lineについて記事にしました。

本記事では、細かい構文に迷ったら、例からコピー&ペーストして使えることを目指しました。少しでもお役に立てますと幸いです。

データを行単位で処理する方法は2種類

LinuxなどUNIX系の環境でデータを行単位で処理したいなら、主にやり方は2つあります。

[データを行単位で処理する方法]

  • その1:AWKを使ってデータを行単位に読み込んで処理する
  • その2:シェルスクリプトのwhile read line句を使う<本記事の内容>

その1:AWKを使う方法

AWKは行単位にテキストデータを処理するためのプログラミング言語(スクリプト言語)です。

データを加工したり区切ったり、少々複雑なテキスト処理をする場合はシェルで処理するよりもAWKにデータを渡して処理した方が便利です。

AWKで/etc/passwdからログイン不可のユーザ(/usr/bin/false)を抽出して加工して表示するプログラム例

cat /etc/passwd |\
awk -F: '$7=="\/usr\/bin\/false"{print $1 " - " $5}'

その2:while read line句を使う方法

こちらが本記事のテーマです。

以下では、AWKを使わずに純粋なシェルスクリプトだけでテキストデータに対し行単位に処理を行っていく方法を解説します。

bashにおけるwhile read lineの使い方

bashにおけるwhile read lineの使い方

1.”外部のファイル”を行単位で処理

while read lineのうちlineは変数名です。

lineでなくどんな変数名にしてもOKです。

構文

[構文1]

while read 《変数名》
do
《コマンド》
done < 《ファイル名》

具体例

例:os.txtから一行ずつ読み込んだ文字列を出力する

 
while read line
do
  echo "read line:$line"
done < ./os.txt
 

以下のように、一行ずつ読み込む対象のテキストを別途用意します。

windows
mac
linux

実行結果は以下の通りです。

read line:windows
read line:mac
read line:linux

2."シェル内に定義したデータ"を行単位で処理

外部ファイルを読み込まずにwhile read lineを使う方法

while read lineを使う場合、以下の構文を用いると外部ファイルを読み込まずに使うことができます。

構文

[構文2]

while read line
do
《コマンド》
done < 《キーワード》
《データ》
《キーワード》

《キーワード》はEOFENDなど何でもOKでして、読み込むテキストの開始と終了を判定するものです。

具体例

例:一行ずつ読み込んだ文字列を出力する

 
while read line
do
  echo "read line:$line"
done < EOF
windows
mac
linux
EOF
 

この場合でも、実行結果は同じです。

read line:windows
read line:mac
read line:linux

別の書き方

個人的にEOFENDが好きではありません。その場合、以下のようにも記述できます。

[構文3]

echo '《データ》' | while read line
do
《コマンド》
done

シングルクォートは、《データ》を改行するために必須です。テキストが次の行に続いているよ、というのを表現しています。

具体例

例:echoで一行ずつ読み込んだ文字列を出力する

 
echo 'windows
mac
linux' | while read line
do
  echo "read line:$line"
done
 

この場合でも、実行結果は同じです。

read line:windows
read line:mac
read line:linux

3."コマンド実行した結果出力"を行単位で処理

上のechoの例と同じ構文を使えば、echo以外のコマンド実行結果を1行ずつ処理することができます。

構文

[構文4]

《コマンド1》 | while read line
do
《コマンド2》
done

具体例

cat os.txt | while read line
do
  echo "read line:$line"
done
 
read line:windows
read line:mac
read line:linux

コマンド結果を使うので、より複雑なコマンドを実行した結果を1行ずつ処理するのに便利です。
次の例では、小文字を大文字に変換してから1行ずつ処理を実行します。

cat os.txt | tr 'a-z' 'A-Z' | while read line
do
  echo "read line:$line"
done
 
read line:WINDOWS
read line:MAC
read line:LINUX

行をさらにカラム(単語)に分けて処理する

最初のAWKのプログラムと同じように、行単位かつ単語単位でデータを区切って(コロン:区切り)処理してみます。

なお、/etc/passwdはこんな感じのコロン区切りのデータです。

nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
_cvs:*:72:72:CVS Server:/var/empty:/usr/bin/false

AWKとbash/while read lineでの行単位処理を比べる

最初に解説した、/etc/passwdからログイン不可のユーザ(/usr/bin/false)を抽出して加工して表示する例を、①AWKで書いた場合、②bashのwhile read lineで書いた場合それぞれのコード例を示します。

①AWKで処理する場合

cat /etc/passwd |\
awk -F: '$7=="\/usr\/bin\/false"{print $1 " - " $5}'

②bashで処理する場合

cat /etc/passwd | while IFS=: read \
user d uid gid detail home shell
do
[ "$shell" = "/usr/bin/false" ] && echo "$user - $detail"
done

for文でwhile read lineを代替する方法

for文でwhile read lineを代替する方法

物覚えの悪い私は、あまりwhile read lineを使いません。多くの場合、for文で表現できるからです。

[構文5]

for 《変数名》 in `cat 《ファイル名》`
do
《コマンド》
done

具体例

例:for文での代替例

 
for x in `cat ./os.txt`
do
 echo $x
done
 

この場合でも、実行結果は同じです。

read line:windows
read line:mac
read line:linux

for文で代替できないケース

各行に空白を含む場合、for文ですと改行だけでなく空白でも区切られてしまうのでwhile read lineを使った方が便利です。

windows 10
mac OS X
linux

for文を使うとこうなってしまいます。

read line:windows
read line:10
read line:mac
read line:OS
read line:X
read line:linux

つまり、for文では行単位ではなく単語単位で処理するということですね。
 

bashならこちらの書籍がオススメです

Blog TOP  シェルスクリプトを勉強したい人向け|bashの使い方 記事まとめ

bashの使い方 - もくじ

bashの使い方 - もくじ

シェルとは

 - シェルとは
 - シェルはOSと会話するための言語
 - シェルの種類(bash以外のシェル)
 - シェルスクリプトとは
 - シェルスクリプトの書き方

条件式

 - if else文
 - 文字列の比較
 - &&と||の使い方
 - case文

文字列操作

 - 文字列の連結
 - 文字列の一部を切り出す

繰り返し

 - for文
 - while文
 - while文でリストから1つ要素ずつ処理する

定数

 - 定数の定義

関数

 - 関数の定義

デバッグ

 - デバッグオプション(-x)

実行権限

 - 実行権限のないシェルスクリプトファイルを実行する

 - シェルスクリプトの書籍3選