2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

車輪の再発明:Bashライブラリ内の関数定義をShellScriptにマージするlibMerge

Last updated at Posted at 2017-02-19

前書き

本記事では、自作したPython3.xスクリプトのlibMergeについて記載します。
libMergeは、Bashライブラリ内の関数定義をShellScriptにマージする機能を持ちます。
正確には、Script内で使用されている関数の定義部分のみをBashライブラリから抽出し、
「抽出した関数+元々のScriptの内容」を記載したScriptを新規作成します。

なお、libMergeの作成理由は、以下の通りです。
 1. Bashは汎用的なライブラリが存在せず、ライブラリ内の関数の機能に関する共通認識がない。
   そのため、第三者が関数定義を参照しやすいScriptの提供が好ましい。
 2. 第三者のために、ライブラリの関数定義をScriptに手動で転記する事は避けたい。
 3. 単一のファイルで完結していないScriptは、可搬性が低い。
   ライブラリがインクルードできない場合、ライブラリが改変された場合などは動作しなくなる。

ちなみに、2005年に「シェルスクリプトを共有してマージするshsubrmerge(CodeZine)」という記事で、
ほぼ同じ機能のScriptが公開されています。まさに、車輪の再発明です。
さらに言及すれば、同等の機能を持つ有名なパッケージが存在しないようなので、
需要がない事が予想されます。自分の問題を解決できるから良いんだ(・言・)

目次

 1. libMergeのインストール
 2. 参考ライブラリ:bashLib
 3. libMergeのオプション
 4. libMergeの使用手順
 5. libMergeの処理(仕組み)
 6. Limitation

libMergeのインストール

Githubに公開してあるため、以下の手順(Debian想定)で取得できます。
libMergeのインストールディレクトリは、"/usr/local/bin/"以下となります。

$ git clone https://github.com/nao1215/BashScriptsCompilation.git -b master
$ cd BashScriptsCompilation
$ sudo ./installScripts         # インストールスクリプト

サンプルライブラリ:bashLibについて

Bashライブラリをお持ちの方は少ないと思われるので、サンプルライブラリbashLibを用意しました。
先ほどのインストール手順によって、bashLibもインストールされます。

なお、bashLibに存在する関数は、以下の通りです。

関数名 説明
errMsg 標準出力にエラーメッセージを赤文字で表示
warnMsg 標準出力にエラーメッセージを黃文字で表示
checkArgc 引数の個数をチェック
isFile ファイルが存在するかどうかをチェック
isDir ディレクトリが存在するかどうかをチェック
isSubshell scriptが"source"コマンドで実行されているかを確認
isNumeric 変数が数値化どうかをチェック
isNull 変数(文字列)がNullかどうかをチェック
isRoot ユーザがrootかどうかをチェック
++ 変数(数値)をインクリメント
-- 変数(数値)をデクリメント
AplusB 変数に指定の値を加算
AminusB 変数に指定の値を減算
_sum 変数(数値)を加算
makeDir 各種確認の後、ディレクトリを作成
makeEmptyFile 各種確認の後、0Byteのファイルを作成
getLineNum ファイルの行数を取得
dos2unix ファイルをwindows形式からunix形式に変換

libMergeのオプション

オプション 説明
-l(--lib) BashライブラリへのPATHを記載。
-s(--script) ライブラリ内の関数定義を付与したいScriptへの
PATHを記載。
-o(--output) 関数定義を転記したスクリプト(新規作成)の名前を
変更したい場合、ファイル名を記載。
(デフォルト:"m_<original_scriptname>)"

libMergeの使用手順

例として、以下のようなサンプルスクリプト(sample.sh)を用意します。
sample.shでは、"/usr/local/bin/bashLib"内で定義されたmakeDir()、errMsg()を使用しています。
これらの関数を使用するため、"source"コマンドによってライブラリをインクルードする必要があります。

sample.sh
#!/bin/bash
# Description : Sample Script

source /usr/local/bin/bashLib  # ライブラリのインクルード
makeDir "dir"                  # ライブラリ関数
errMsg "Sample"             # 同上
実行結果.
$ ./sample.sh 
make directory dir
Sample

libMergeを用いて、前述のsample.shに、関数定義を付与します。
なお、sample.shに直接関数の定義を挿入するのではなく、m_sample.shという新規Scriptが生成されます。
ここでの新規Scriptの名前は、"-o"オプションで変更する事ができます。

$ ls
sample.sh
$ libMerge -s sample.sh -l /usr/local/bin/bashLib
$ ls
m_sample.sh  sample.sh

生成されたm_sample.shは、以下の通りです。
関数定義はScriptのヘッダ以下に挿入され、Script(sample.sh)で用いられている関数定義しか転記されません。

m_sample.sh
#!/bin/bash                                                                           
# Description : Sample Script
function errMsg() {
    local message="$1"
    echo -n -e "\033[31m\c"  # Escape sequence to make text color red 
    echo "${message}"
    echo -n -e "\033[m\c"   # Escape sequence to restore font color
}

function makeDir() {
    local dir_path="$1"

    checkArgc "$#"
    if [ -d "${dir_path}" ]; then
        echo "Directory "${dir_path}" already exists. Not make it."
    else
        mkdir -p $1
        if [ "$?" = 0 ]; then
            echo "make directory "${dir_path}""
        fi    
    fi  
}


source /usr/local/bin/bashLib  # ライブラリのインクルード

makeDir "dir"
errMsg "Sample"

libMergeの処理(仕組み)

以下に、libMergeの処理の概要を示します。

 1. オプションチェック(不備があればエラー通知)
 2. Bashライブラリをパースし、関数定義の開始行番号と終了行番号のリストを作成
 3. Bashライブラリに存在する関数の名前を取得
 4. 手順2の結果を元に、関数単位で関数の定義部分を取得。関数名をキー値として、定義を辞書で管理
 5. Scriptをパースし、Script内で使用している関数以外をリスト、辞書から削除
 6. Scriptのコピー(m_<script_name>)の作成中、辞書の要素(関数定義)をScriptのヘッダ以下に挿入

Limitation

 ・関数定義部分の抽出(特に定義終了部)は、改良の余地があります。
 ・元のScriptに存在するライブラリインクルード処理を削除する機能は、未実装です。
 ・十二分なテストを実施していません。

最後に

「2017年の目標に"パッケージ作成(C言語)"があるから、libMergeをC言語で実装しよう」
そのような事を設計時(20117/2/17の睡眠時)に考えましたが、Pythonで実装して正解でした。

また、Bashのライブラリ化を難しくしている原因は、
「戻り値の欠如」「リダイレクト・パイプを駆使するBashの性質」ではないかと、
今回のlibMergeおよびbashLibの作成で身を持って体感しました。
ライブラリ化の利点は、「ワンライナー(シェル芸)の可読性向上」「テンプレ処理の集約」ぐらいで、
それ以上を求めた優れたライブラリの作成を試みる場合、泥沼に陥りそうです。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?