シェルスクリプトでコマンドを呼び出してほとんどのパラメータを渡し、パラメータにスペースを入れます。

シェルスクリプトでコマンドを呼び出してほとんどのパラメータを渡し、パラメータにスペースを入れます。

SASコードを一括実行するコマンドの周りにrun_sas.shラッパーがあります。sas一般的な通貨は次のとおりです。

./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder/my_program.log
  • run_sas.shすべてのパラメータをsaswithに渡します./sas $*
  • sasその後、実行して/my_code/my_program.sasログを作成します/my_log_folder/my_program.log
  • 次にrun_sas.sh呼び出しパラメータを分析します。
  • そして、ログを次の場所にコピーします。/admin/.hidden_log_folder/my_program_<today's date>.log

2つのことを変更したい。

マルチワードパラメータの有効化

一部のクライアントは、フォルダとファイル名にスペースを使用して実行する必要があることを絶対に望んでいます/their code/their program.sas

./run_sas.sh -sysin "/their code/their program.sas" -log "/their log folder"

/their code/their program.sas/their log folder単一の引数を渡す必要があります。sas

特定のパラメータを削除

./sas_utf8時には代わりに実行する必要があり./sas、2番目のスクリプトを維持するのはあまりにも怠惰なので、次の追加パラメータを許可したいと思います。

./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder -encoding utf8

電話で通話可能

./sas_utf8 -sysin /my_code/my_program.sas -log /my_log_folder

変える

./sas -sysin /my_code/my_program.sas -log /my_log_folder

できれば、これを行うにはどうすればよいですかksh

答え1

まず、パラメータをそのまま維持するには、"$@"not $*(または)を使用してください。を$@使用するのと同じように、各パラメータを別々の単語に展開します。"$1" "$2"...を使用すると、$*glob文字も問題になります。

utf8オプションを見つけるには、コマンドライン引数を繰り返し、保持したい引数を別の配列にコピーし、と表示されたら-encodingフラグを設定できますutf8

その後、フラグ変数を調べて実行するプログラムを決定し、それをコマンド"${sasArgs[@]}"に渡します。

だから:

executable="./sas" # The default, for latin encoding

# Inspect the arguments,
# Remember where the log is written
# Change the executable if the encoding is specified
# Copy all arguments except the encoding to the 'sasArgs' array
while [[ "$#" -gt 0 ]]; do
    case "$1" in
        -encoding) 
            # change the executable, but do not append to sasArgs
            if [[ "$2" = "utf8" ]]; then
                executable="./sas_u8"               
                shift 2
                continue
            else
                echo "The only alternative encoding already supported is utf8" >&2
                exit 1
            fi
            ;;
        -log) 
            # remember the next argument to copy the log from
            logPath="$2"
            ;;
    esac
    sasArgs+=("$1")
    shift
done

#  To debug: print the args, enclosed in "<>" to discover multi word arguments
printf "Command and args: "
printf "<%s> " "$cmd" "${sasArgs[@]}"
printf "\n"
# exit # when debugging

# Actually run it
"$executable" "${sasArgs[@]}"

# Copy the log using $logPath
# ...

最後のprintf呼び出しは各引数を囲んで実行する引数を印刷するため、空白の<>引数が変更されていないことを確認できます。 (実行できますが、2つの引数と1つの引数をecho "${sasArgs[@]}"区別しません。)foobarfoo bar


2つのパラメータペアではなく単一のパラメータを見つけると、最初の部分はループを使用してより簡単になりますfor

for arg in "$@" do
    case "$arg" in
        -encoding-utf8) 
            # change the executable, but do not append to the array
            executable="./sas_u8"               
            continue
            ;;
     esac
     sasArgs+=("$arg")
done

通常のPOSIX shに変換することもできます。ループforは与えられたリストのコピーを作成するので、コピーされた引数は配列を使用するset -- "$@" "$arg"代わりに位置引数(追加)として保存することができます。

さらに、最初にエンコードパラメータを知っている場合は、トランザクション全体がはるかに単純になります。その後、(および)を確認してを使用して削除するだけで$1十分です。$2shift

(私はDebianでBashとksh93の両方のバージョンを使って上記のスクリプトをテストしました。私はkshに慣れていないので何かを逃したかもしれません。

関連情報