##概要
コメントアウトを用いることで簡単に原因の特定をする方法を紹介いたします。
とても基礎的な内容ですが、自分で本当に理解できているのかどうか、この記事を書くことを通して確認したいと思います。
前提
chmodをした上で、bashのスクリプトvar.shを出力した時にエラーが出るので原因と特定してなんとかしたい。そのためにはコメントアウトが役に立つというお話。
そもそもコメントアウトって?
コードの行頭に一般的に#と書く事で「コードとしては一応書いてはあるが認識させないようにする技法」のことを指します。#かどうかはプログラミング言語によりますし、一度に複数行コメントアウトできる言語もあります。
例1:コメントアウトなしの場合
hello.sh
#!/bin/bash
echo "Hello world!"
$ bash hello.sh
Hello world!
例2:コメントアウトありの場合
echoの前に#を足してみます。
hide_hello.sh
#!/bin/bash
#echo "Hello world!"
$ bash hide_hello.sh
$
何も表示されません。以上のことを表にまとめてみます。
| | コード | 出力結果|
|:-:|:-:|:-:|:-:|
| hello.sh | echo "Hello world!" | Hello world! |
| hide_hello.sh | #echo "Hello world!" | (何も表示されない) |
つまり、「コードとしては(一応)存在はしているが、認識されなくなる」というのがコメントアウト(#)の役割です。
コメントアウトを問題解決に用いる
以下のようなコードを書いたがエラーが出たが、どこに原因があるのかがわからない場合を想定し、それに対してコメントアウトを用いて問題解決をします。
例1:このサンプルコードを使っていきます
var.sh
#!/bin/bash
#A
function datetime() {
#A-1
DATE=`date '+%Y-%m-%d'`
TIME=`date '+%H:%M:%S'`
#A-2
echo ${DATE}${TIME}
echo DATETIME
echo $DATETIME
}
#B
datetime()
$ bash var.sh
var.sh: line 17: syntax error: unexpected end of file
エラーになってしまいました。コードを要素にバラして表にします。
以下、コメントアウトしていない箇所を「表示」、コメントアウトした箇所を「非表示」とします。
A-1 | A-2 | B | 出力結果 | |
---|---|---|---|---|
例1 | 表示 | 表示 | 表示 | error |
じゃあこの問題をどう解決するのか。タイトル通り、コメントアウト(#)を使います。
「コードとしては(一応)存在はしているが、認識されなくなる」というのがコメントアウトの特徴なので、その特徴を活かして原因の特定に役立つことを見ていきます。
例2:全部コメントアウトしてみる
例1を一度すべてコメントアウトをしてここに原因があることを確認してみます。
#!/bin/bash
# すべての要素をコメントアウトした
##A
#function datetime() {
# #A-1
# DATE=`date '+%Y-%m-%d'`
# TIME=`date '+%H:%M:%S'`
#
# #A-2
# echo ${DATE}${TIME}
# echo DATETIME
# echo $DATETIME
#}
#
##B
#datetime()
$ bash var.sh
$
何もエラーが出ませんでした。表に追加して意味を読み取ります。
| | A-1 | A-2 | B | 出力結果|
|:-:|:-:|:-:|:-:|:-:|:-:|
| 例1 | 表示 | 表示 | 表示 | error |
| 例2 | 非表示 | 非表示 | 非表示 | errorなし |
例1と例2から、このファイルのなんらかの記述が原因でエラーを吐いていることが確認できます。(当然ですが)
この作業を構造的に繰り返していくとエラーの特定ができることをみていきます。
例3:1/3コメントアウトしてみる(その1)
A-1だけコメントアウトしてみます。
コード
#!/bin/bash
#A
function datetime() {
##A-1 A-1だけコメントアウトした
#DATE=`date '+%Y-%m-%d'`
#TIME=`date '+%H:%M:%S'`
#A-2
echo ${DATE}${TIME}
echo DATETIME
echo $DATETIME
}
#B
datetime()
出力結果
$ bash var.sh
var.sh: line 17: syntax error: unexpected end of file
エラーでした。表に追加して意味を読み取ります。
| | A-1 | A-2 | B | 出力結果|
|:-:|:-:|:-:|:-:|:-:|:-:|
| 例1 | 表示 | 表示 | 表示 | error |
| 例2 | 非表示 | 非表示 | 非表示 | errorなし |
| 例3 | 非表示 | 表示 | 表示 | error |
例1~3から、A-2とBが表示されているならばerrorのようです。では、じゃあA-2かBが原因っぽいですね。
次はA-2だけをコメントアウトしてみます。
例4:1/3コメントアウトしてみる(その2)
A-2をコメントアウトします。
#!/bin/bash
#A
function datetime() {
#A-1
DATE=`date '+%Y-%m-%d'`
TIME=`date '+%H:%M:%S'`
##A-2 次はここだけをコメントアウトしました
#echo ${DATE}${TIME}
#echo DATETIME
#echo $DATETIME
}
#B
datetime()
$ bash var.sh
var.sh: line 17: syntax error: unexpected end of file
エラーが出ました。表に追加して意味を読み取ります。
| | A-1 | A-2 | B | 出力結果|
|:-:|:-:|:-:|:-:|:-:|:-:|
| 例1 | 表示 | 表示 | 表示 | error |
| 例2 | 非表示 | 非表示 | 非表示 | errorなし |
| 例3 | 非表示 | 表示 | 表示 | error |
| 例4 | 表示 | 非表示 | 表示 | error |
このファイルが要素A-1とA-2とBで構成されていて、その上でエラーが出ています。また、例2~4から、A-1とA-2がerrorの原因でないということがわかります。ということは...??
例5:1/3コメントアウトしてみる(その3)
Bをコメントアウトします。
#!/bin/bash
#A
function datetime() {
#A-1
DATE=`date '+%Y-%m-%d'`
TIME=`date '+%H:%M:%S'`
##A-2
echo ${DATE}${TIME}
echo DATETIME
echo $DATETIME
}
#B ここをコメントアウトした
#datetime()
$ bash var.sh
$
おお。エラーがなくなりました。表に追加します。
| | A-1 | A-2 | B | 出力結果|
|:-:|:-:|:-:|:-:|:-:|:-:|
| 例1 | 表示 | 表示 | 表示 | error |
| 例2 | 非表示 | 非表示 | 非表示 | errorなし |
| 例3 | 非表示 | 表示 | 表示 | error |
| 例4 | 表示 | 非表示 | 表示 | error |
| 例5 | 表示 | 表示 | 非表示 | errorなし |
この表の意味を読み取ります。
要素Bが表示されて__いる__ → 出力結果が__error__
要素Bが表示されて__いない__ → 出力結果が__errorなし__
という関係が見られました。なので、このerrorはBが怪しいようです。
あとは怪しいであろうdatetime()を要素に分解して、同じように調べていくだけです。
ちなみに、この例のdatetime()ではぱっと見で原因が掴めるので分解する必要性は高くないのですが、見慣れないメソッドなどの場合、以下のようにバラバラにしていきます。
bashスクリプトのfunctionの呼び出しは、
関数呼び出し = 呼び出す関数名 + 引数部分
という構成になっています。なので、datetime()を関数datetimeと引数部
分()にさらに分解して、同じようにコメントアウトで比較していきます。(例は省略します)
例 | datetime | () | 結果 |
---|---|---|---|
例1 | 非表示 | 非表示 | errorなし |
例2 | 表示 | 表示 | error |
例3 | 表示 | 非表示 | errorなし |
例4 | 非表示 | 表示 | error |
この表の意味を読み取ります。
例2から「関数datetimeを表示し、かつ、引数()を__表示__」ならば__error__
例3から「関数datetimeを表示し、かつ、引数()を__非表示__」ならば__errorなし__
という関係が見られました。つまり、datetime関数呼び出しの際の引数()が悪さをしていたんですね。
datetime関数呼び出しの際の引数()をコメントアウトをしてみます。
例6:原因をピンポイントでコメントアウトしてみる
#!/bin/bash
#A
function datetime() {
#A-1
DATE=`date '+%Y-%m-%d'`
TIME=`date '+%H:%M:%S'`
#A-2
echo ${DATE}${TIME}
echo DATETIME
echo $DATETIME
}
#B
#datetime関数の後の()をコメントアウトした。
datetime #()
$ bash var.sh
2016-12-1821:54:00
DATETIME
$
エラーが解決しました。
以上より、var.shのエラーの原因は要素Bの関数datetimeを呼び出す際に余分な引数である()が指定されていることであるとわかりました。コメントアウトを構造的に行っていくと簡単に問題解決できるよ、というお話でした。
非常に拙い内容ですが、最後まで見ていただきありがとうございました。