0

誰かが次の使用法を処理する簡単な bash スクリプトを書くのを手伝ってくれませんか:

./application channels;message

eg:  ./application channel1 channel2 channel3;this is a message

したがって、基本的に区切り記号の前のすべて; スペースで区切られたチャンネルと、; の後のものです。がメッセージです。

基本的に、これらのそれぞれを変数に保存して印刷したかったのです...

4

4 に答える 4

2

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を参照してください。

于 2013-02-18T23:03:12.740 に答える
1

おそらく、メッセージを区切る別の方法を探す必要があります。セミコロンがあると、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

于 2013-02-18T22:50:16.333 に答える
0
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
于 2013-02-18T23:01:52.913 に答える
0

次のカットコマンド を使用できます。

#!/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
于 2013-02-19T00:09:38.977 に答える