誰かが次の使用法を処理する簡単な bash スクリプトを書くのを手伝ってくれませんか:
./application channels;message
eg: ./application channel1 channel2 channel3;this is a message
したがって、基本的に区切り記号の前のすべて; スペースで区切られたチャンネルと、; の後のものです。がメッセージです。
基本的に、これらのそれぞれを変数に保存して印刷したかったのです...
1 つのメッセージと 1 つ以上のチャネルが必要なため、最初にメッセージを指定してから、残りの引数がチャネルであると想定する方が理にかなっています。何かのようなもの
#!/bin/bash
message="$1"
shift # Now each argument in $@ is a channel
次に、スクリプトを次のように実行できます
$ ./application "This is a message" channel1 channel2 channel3
これは通常、必要な引数を処理する方法ですが-m
、メッセージを指定するために使用する場合と比較した場合の欠点の 1 つは、ユーザーがメッセージを指定するのを忘れたかどうかを判断するのが難しいことです。
# Is "channel1" the message, or did the user forget to specify one?
$ ./application channel1 channel2 channel3
実装については、 Jonathan Leffler's answer-m
を参照してください。
おそらく、メッセージを区切る別の方法を探す必要があります。セミコロンがあると、bash はセミコロンまで読み取り、「これでコマンドの終わりだと思う」ことになるからです。次に、bash は、セミコロンの前に引数を指定してプログラムを実行します。続いて、「this」という名前のプログラムまたはビルドインを探し、コマンドライン引数として「is」、「a」、および「message」を this に提供します。ただし、bash はおそらく「this: command not found」で応答します。詳細については、bash のマニュアルで「;」/セミコロン演算子の意味を調べてください。
あなたができることは、次のようなものです
#!/bin/bash
message=""
outfiles=""
# Loop until all parameters are used up
# shift "eats" one argument at a time
# util there are no arguments left then $1 is a emtpy string
while [ "$1" != "" ]; do
if [ "$1" == "-m" ] # the message
then
shift #"eat one arugment then $1 is your message"
#you should check if there is a argument after "-m"
message=$1
else
outfiles="$outfiles $1"
fi
# Shift all the parameters down by one
shift
done
# put the message it the other arguments specified.
for i in $outfiles; do
echo $message > $i
done
このプログラムが行うことは、「-m」をチェックすることです。次に、すべての引数をシフトして、引数を1つマイナスし、このメッセージを他の引数に書き込みます。例: $./program.bash -m "Hello world" output1.txt ouput2.txtこのプログラムは、「Hello world」というメッセージを、新しく作成されたファイルまたは (注意して) 上書きされたファイルに出力します output1.txt output2.txt
while getopts m: opt
do
case "$opt" in
(m) message="$OPTARG";;
(*) echo "Usage: $0 [-m 'message'] [chan ...]" >&2; exit 1;;
esac
done
shift $(($OPTIND-1))
for channel in "$@"
do
whatever -y because -m "$message" $channel
done
それはうまくいくはずです。メッセージはオプションのままで、チャネルを指定する必要はありません。オプションをかなり簡単に追加できます (文字の後にコロンで指定された引数を取るもの、コロンなしでは引数を取らないもの)。$#
2 つのループ間で 0 より大きいと主張することができます (ただし、それを反映するように使用法メッセージを変更する必要があります)。メッセージが渡されるように主張することもできます (ただし、そのためには使用法メッセージも変更する必要があります)。そして、それは続きます。あなたの選択肢はたくさんあります。
コメントで述べたように:
;
シェルへのコマンド区切り文字であることに注意してください。あなたは書く必要があります:
./application 'channels;message'
セミコロンまたはその前のバックスラッシュを引用符で囲みます。これはあまりオーソドックスな使い方ではありません。次のようなより慣用的な表記法を使用できます。
./application -m "this is a message" channel1 channel2 channel3
上記のスクリプトは、この提案をかなり正確に実装しています。
私が見る唯一の問題は、メッセージに
"
文字が含まれている場合です。./application -m "this isn"t a message" channel1
等...
を含むシェルのメタ文字を認識する必要があります"'`$;(
。これらすべてについて、犯人キャラクターをエスケープする必要があります。
./application -m 'He said, "Don'\''t do that!"' chan1
通常、メッセージは一重引用符で囲みます。一重引用符を書く必要がある場合は、'\''
代わりに入力してください。
./application -m 'He said, "This is a message."' chan1
./application -m "This isn't a message." chan2
./application -m 'He said, "This isn'\''t a message", but they disagreed." chan3
次のカットコマンド を使用できます。
#!/bin/bash
variables=`echo $* | cut -d';' -f1`
message=`echo $* | cut -d';' -f2`
echo "variables: " $variables
echo "message: " $message
必ず\
セミコロンをエスケープしてください:
$ ./application channels\;message
channels: channels
message: message