2016/02/03(Wed)bashスクリプトの起動引数をそのまま出力する

2016/02/03 1:38 Software::Linux
タイトルの通り、シェルスクリプトの起動時に、引数に指定されたパラメーター全てをechoしたい(実際はログファイルに保存する意図)という、ただそれだけ。こういうの↓
$ ./arg.sh 1 2 "3 4" 5 '6 7' 8   9
Command line: ./arg.sh 1 2 '3 4' 5 '6 7' 8 9
が、空白を含む文字列が含まれている場合に、それを判別可能な形で出力させるのに手間取ったのでメモしておく。

解答

#!/bin/bash
function arg_escape(){
     local i arg
     for ((i=${#BASH_ARGV[@]}-1; i>=0; i--)); do
         case ${BASH_ARGV[$i]} in
             *\ *)
                 arg+=("'"${BASH_ARGV[$i]}"'")
                 ;;
             *)
                 arg+=(${BASH_ARGV[$i]})
                 ;;
         esac
     done
     echo ${arg[*]}
 }

echo "Command line: $0 $(arg_escape)"
まず思いつくであろう"$@"を使えば、空白を維持したままで各引数のパラメータを取り出せるが、これには問題点が一つ。
functionの中に入れた場合には、$@がfunctionを呼び出したときの引数で置き換わってしまうため、例えば、
$(arg_escape "$@")
のようにして呼ぶ必要が出てくる。
例えば、共通のfunctionを定義したとして、callerに"$@"を決めうちで渡してもらうのは、あまり格好がよくない。

解決策は、bashで起動すると$BASH_ARGVというリストが得られるので、これを使うことにする。
が、これにも一癖あり、stack状に積まれているため、単純forループ(for x in~)で取り出すと、本来の指定と逆順になるのである。
これをナントカするために、地道なfor文を書く。

で、ループ処理する時点で、クオーテーションやダブルクオーテーションが外れてしまうので、それを復元する。まあ、今回は環境変数があっても展開して欲しくないので、シングルクオートで囲っておく。

実際に動かしてみると、こんな感じ。
ダブルクオーテーションがシングルクオーテーションになっていること以外は、問題無く復元に成功。
もう一度、出力例を貼っておく。
$ ./arg.sh 1 2 "3 4" 5 '6 7' 8   9
Command line: ./arg.sh 1 2 '3 4' 5 '6 7' 8 9
一つだけ。
エスケープを復元する所では空白文字だけしか考慮していないが、もし、シングルクオート自体が入力される可能性がある場合は、その処理も足す必要があることに注意。上記例では、こんな感じになってしまう。
$ ./arg.sh 1 "2'3"
Command line: ./arg.sh 1 2'3