先日、Twitter上でタイトルのようなお題が出ていたので、少し調べてみた。
ただ単に空行だけを排除するならば、以下のようなやり方がある。

grep . PATH
sed '/^$/d' PATH

ただし、これらだとスペースやタブだけの行については排除してくれない。

[root@BS-PUB-CENT7-01 tmp]# 行末は「$」、タブは「^I」で表示されている
[root@BS-PUB-CENT7-01 tmp]# cat -ET /tmp/test7.txt
111$
222$
$
333$
4444$
   $
  5555 $
  556566 $
^I$
66465$
[root@BS-PUB-CENT7-01 tmp]# grep . /tmp/test7.txt
111
222
333
4444

  5555
  556566

66465
[root@BS-PUB-CENT7-01 tmp]# sed '/^$/d' /tmp/test7.txt
111
222
333
4444

  5555
  556566

66465

じゃ、こういったタブやスペースのみが存在している行を排除するには、どうすればよいのか?
とりあえず確認できている対処法は以下の2つ。

awkでやる

おそらく、このawkでやるやり方が一番シンプルかつ短い。
以下のようにawkを実行してやることで、すべての空行やタブ・スペースのみの行を除外することができる。

awk NF ファイルPATH
[root@BS-PUB-CENT7-01 tmp]# cat -ET /tmp/test7.txt
111$
222$
$
333$
4444$
   $
  5555 $
  556566 $
^I$
66465$
[root@BS-PUB-CENT7-01 tmp]# awk NF /tmp/test7.txt
111
222
333
4444
  5555
  556566
66465

sedでやる

sedでやる場合では(あとでやるgrepもそうだけど)、"スペースやタブのみの行について削除"して出力する方法と、"スペース以外の文字列を抽出"する方法の2つのアプローチがありそうだ。

sed '/^[[:blank:]]*$/d' PATH # タブやスペースのみの行を削除する
sed '/^\s*$/d' PATH # タブやスペースのみの行を削除する
sed -n '/\S/p' PATH # タブやスペース以外の文字列のみを抽出する
[root@BS-PUB-CENT7-01 tmp]# cat -ET /tmp/test7.txt
111$
222$
$
333$
4444$
   $
  5555 $
  556566 $
^I$
66465$
[root@BS-PUB-CENT7-01 tmp]# # タブやスペースのみの行を削除する
[root@BS-PUB-CENT7-01 tmp]# sed '/^[[:blank:]]*$/d' /tmp/test7.txt
111
222
333
4444
  5555
  556566
66465
[root@BS-PUB-CENT7-01 tmp]# sed '/^\s*$/d' /tmp/test7.txt
111
222
333
4444
  5555
  556566
66465
[root@BS-PUB-CENT7-01 tmp]# # タブやスペース以外の文字列のみを抽出する
[root@BS-PUB-CENT7-01 tmp]# sed -n '/\S/p' /tmp/test7.txt
111
222
333
4444
  5555
  556566
66465

一応解説。
bashのメタキャラクタで「\s」は空白文字を、「\S」は空白以外の文字を表している。
つまり、↑のsedの書き方だと、それぞれ以下のような意味を持っている。

  • sed '/^\s*$/d' PATH
    … 「^」で行頭、「$」で行末を表している。「\s*」でスペース・タブの0回以上の繰り返しとなるので、行頭から行末までの間にスペースやタブしか存在しない行を削除(sedでは/~/dで削除になる)している。
  • sed -n '/\S/p' PATH
    … 「\S」で空白以外の文字列を表しているので、それだけ出力させている(-n /~/pで対象行のみ出力)。

grepでやる

grepでやる場合もsedと同じようなアプローチの仕方になる。

grep -v "^\s*$" PATH # タブやスペースのみの行を削除する
grep "\S" PATH # タブやスペース以外の文字列のみを抽出する
[root@BS-PUB-CENT7-01 tmp]# cat -ET /tmp/test7.txt
111$
222$
$
333$
4444$
   $
  5555 $
  556566 $
^I$
66465$
[root@BS-PUB-CENT7-01 tmp]# # タブやスペースのみの行を削除する
[root@BS-PUB-CENT7-01 tmp]# grep -v "^\s*$" /tmp/test7.txt
111
222
333
4444
  5555
  556566
66465
[root@BS-PUB-CENT7-01 tmp]# # タブやスペース以外の文字列のみを抽出する
[root@BS-PUB-CENT7-01 tmp]# grep "\S" /tmp/test7.txt
111
222
333
4444
  5555
  556566
66465