次の簡単なスクリプトがあります。
- 電子メールが特定のパターンと一致することを確認する
- その場合は、タグリストにタグを追加してください。
- 終了する前にタグリストを印刷してください。
set -e
lista_tag=()
in_file="/tmp/grepmail-classify.txt"
# save stdin to file, to use it multiple times
cp /dev/stdin $in_file
# CLASSIFY
res=$(grepmail -B "some regex pattern" < $in_file)
if [ ! -z "$res" ]
then
lista_tag+=("PUSH")
fi
res=$(grepmail -B "some other regex pattern" < $in_file)
if [ ! -z "$res" ]
then
lista_tag+=("MERGIFY")
fi
# ⁝ Many many more similar patterns
# output them comma separated
echo ${lista_tag[*]}
ご覧のとおり、リファクタリングと抽象化の場合があります。res
そしてif .. fi
部分的に繰り返された。しかし、コマンドを安全に渡す方法がわかりません。私がしたいのは、次のような(または同様の)関数を呼び出すことです。
classify '"grepmail -B "somepattern"' 'MYTAG'
しかし、トリッキーです!私が読んでよくある質問しかし、私の場合はうまくいくかわかりません。
したがって、質問は次のようになります。コマンドを渡す正しい方法は何ですか(存在する場合)?res=
そのような機能の一部はどのようなものでしょうか?
ベストアンサー1
classify '"grepmail -B "somepattern"' 'MYTAG'
で述べたまさにその理由のために作業を始めることは困難です。バッシュFAQ 050。
ただし、「tag」パラメーターを前に置くと、コマンドの残りの部分を使用できるため、機能させることができます。
#!/bin/bash
lista_tag=()
classify() {
local tag="$1"
shift
res=$( "$@" < "$in_file")
if [ -n "$res" ]; then
lista_tag+=("$tag")
fi
}
classify PUSH grepmail -B "some regex pattern"
classify MERGIFY grepmail -B "some other regex pattern"
ここでの核心はまさに私たちです。いいえコマンドの引数を1つの文字列に貼り付けますが、別々に保持します。"$@"
それは魔法です。すべての位置パラメータに個別に拡張されます。タグを削除した後に残ったのはコマンドだけです。
ただし、コマンドを実行して適切に引用する必要があるため、同じ方法でリダイレクトを貼り付けることはできませんeval
。また、ユーザーが入力した入力に対してこの作業を慎重に行う必要があります。そうしないと、コマンド実行の脆弱性が残る可能性が高くなります。
とにかく、そのgrepmail -B
部分は定数のように見えるので、ラベルとモードを渡すだけです。
#!/bin/bash
lista_tag=()
in_file=foo.txt
classify() {
local pattern="$1"
local tag="$2"
if [[ -n "$(grepmail -B "$pattern" < "$in_file")" ]]; then
lista_tag+=("$tag")
fi
}
classify "some regex pattern" PUSH
classify "some other regex pattern" MERGIFY