コマンドを渡すには?

コマンドを渡すには?

次の簡単なスクリプトがあります。

  • 電子メールが特定のパターンと一致することを確認する
  • その場合は、タグリストにタグを追加してください。
  • 終了する前にタグリストを印刷してください。
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

おすすめ記事