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

シェル/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選

  • 給付を貰いながら講座を受講して、Linux技術者認定(LPIC-1&2)を短期で取得しませんか?技術力の認定があれば、転職・就職・昇進に有利です。もちろん実務能力も向上します。無料の資料請求はこちら(Linuxアカデミー)   の右上から。
 LPIC資格対策コース(LeveI1):学習時間は15時間  LPIC2資格対策コース(LeveI2):学習時間は25時間  Linuxセキュリティコースもあります:学習時間は25時間  会社員なら、教育訓練給付制度の給付対象となる講座です。  資格試験の内容、学習プラン、講座に関する資料を無料送付。
Linux技術者認定(LPIC Level1&Level2)

キャンペーン情報:無料で1,000円プレゼント Linuxアカデミーでは、教室でカウンセリングを受けた方を対象にスターバックスカード1,000円分の無料プレゼントキャンペーン中です。この機会にぜひどうぞ! » LPIC-1&2 対策コースの詳細はこちら » LinuCライセンスを独学で取得したい方はこちら

Blog TOP  Linuxコマンドを勉強したい人向け|Linuxの使い方 記事まとめ

Linux&Linuxコマンドを勉強したい人向けの記事もくじ

用語解説・技術一般

  "UNIXとLINUX"の違いについて解説します
  CUIとGUIの違い・特徴について解説します

サーバリソースを確認するコマンドの使い方

  【Linux】CPU使用率を確認する3つの方法を解説します
  【Linux】topコマンドで,CPU消費の原因を特定する方法
  【Linux】ps実行時に-efオプションを付ける理由について
  【Linux】メモリ使用率を確認する|容量・空きの確認も
  【Linux】ディスク容量を確認する|ディスク容量監視も

ファイル操作に関するコマンドの使い方

  【Linux】ファイルの行数をカウントする方法を解説
  【Linux】文字コード変換ならiconvコマンド1択です
  【Linux】/dev/nullを、エンジニアが使う2つの目的
  【Linux】findのexecオプションの使い方とその注意点
  【Linux】findの結果から圧縮ファイルを作るコマンド
  【Linux】hostsの場所はどこ?→/etc/hostsにあります
  【Linux】touchコマンドで,時刻更新&空ファイル作成

Linux管理者用コマンドの使い方

  【Linux】再起動コマンド(shutdown)の使い方と注意点

よく使う便利なコマンドの使い方

  【Linux】改行なしでechoコマンドを使う時の -nオプション
  【Linux】sleepコマンドの使用例と注意点について解説する
  【Linux】rmコマンドでディレクトリを削除する方法を解説
  【Linux】ファイルを削除するコマンド2選【rm以外もあり】
  【Linux】awkの区切り文字を指定する,-Fオプションを解説
  【Linux】sedで文字列の置換をするeオプションを解説する
  【Linux】dateコマンドのフォーマットとその便利な使い方
  【Linux】大文字から小文字に変換する方法【小文字から大文字も】

シェルの便利機能

  【Linux】コマンド履歴を検索する【Ctrl+r】


今、ITエンジニアは前例のない売り手市場です

ITエンジニアは前例のない売り手市場、転職なら今

現在のエンジニアの求人数と求人倍率をご存知ですか?

直近(※)のIT業界全体の求人倍率は7.85倍です。

つまり 企業が8回 IT人材の求人を出しても、 1人しかエントリーがない 状況です。

エンジニア側が企業を選ぶ なら、今がチャンスです。

※転職サイトdodaが毎月発表している転職求人倍率。
 2019年12月9日発表/集計対象期間は2019年11月1日〜30日

詳しくはこちら


人気記事【今年の抱負】退職しオープン&フリー&シンプルに生きていく【失敗しない働き方改革の本質】