関数によるグローバル変数値パイプの維持

関数によるグローバル変数値パイプの維持

私は小さなbashスクリプトを書いて、sedいくつかのHTMLページからいくつかのURLを抽出するために使用しました。

sed 結果を変数に取り込み、毎回再読み込みを防ぐために、3つの関数を作成し、一緒にパイプしました。

first_function $1 | second_function | third_function

次のように表現してみましょう。

  • 最初の関数は、与えられたリストからアイテムURLを探します。リンクアドレス( $1)
  • 2番目の関数は、各パイプラインURLから画像を抽出します。src
  • 3番目の関数は出力HTMLを組み合わせます。

これでそれをエコーし$lot_url​​てHTMLにすべて入れるsecond_functionことができます。readthird_function$img_url

もっときれいになるアクセス可能なグローバル変数で作成できる場合 second_functionしかし、third_function私はできないようです。

これは、関数間で渡される値の数が増えるほど必要になります。

完全なサンプルコードは次のとおりです。

first_function(){
    curl -s "$1" | sed -nr '
        #extract sub urls
    '
}

second_function(){
    while read lot_url; do
        echo "$lot_url"
        curl -s "$lot_url" | sed -nr '
            #extract img src
        '
    done
}

third_function(){
    while read lot_url; read img_url; do
        echo "<a href="$lot_url"><img src="$img_url" /></a>"
    done
}

first_function "$1" | second_function | third_function

答え1

パイプの両面は異なるプロセスにあります。これらのプロセス間で変数を共有することはできません。データを共有するには、データをパイプするか、代替通信チャネルを使用する必要があります。代替通信チャネルが必要な場合シェルの機能を超えた場合は、実際のプログラミング言語に切り替えてください。

ここでは、2番目のパイプラインで並列化することが私lot_urlにとってはimg_url良い解決策のようです。私はそれらを同じ行に渡します。 URLが正しくエスケープされたと仮定すると、特定の引用符は必要なく、2つの引用符を同じ行に渡すことができます。これはimg_urlそれぞれに可変数のsを許可するという利点がありますlot_url

second_function(){
    while read lot_url; do
        echo "$lot_url"
        curl -s "$lot_url" | sed -nr -e '
            #extract img src
        ' -e "s>^>$lot_url >"
    done
}

third_function(){
    while read lot_url img_url; do
        echo "<a href="$lot_url"><img src="$img_url" /></a>"
    done
}

答え2

ここではwhileループは大丈夫だと思います。とにかく繰り返すたびに実行可能ファイルを呼び出すので、実際に違いがあるとは思いません。このようにしてできる必要なグローバル変数を共有します。良い:

source_cmd |
    while read var
    do  fn1 "$var" |
        fn2 "$var"
    done

しかし、ワークフローを少し変更する方が良いと思いました。この機能は配列ベースのシェルコマンドセットに過ぎません。このような配列は使用しないので、コマンドセットを指す一般的な目的に使用する必要があります。私が見ることができる最も一般的なものですcurl ... | sed ...。引数を取る関数として作成します。したがって、結果は次のようになります。

curl_sed() { url=$1 && shift
    curl -s "$url" | sed -nr "$*"
}
fn() { URL=$1 && shift
    set -- '#extract sub url sed script' \
           '#extract img src sed script'
    curl_sed "$URL" "$1" | 
        while read lot_url
        do  IFS='
';          printf '<a href="'"$lot_url"'"><img src="%s" /></a>\n' \
            $(curl_sed "$lot_url" "$2")
        done
}

あなたはこの質問に対するGilesの答えを受け入れました。明らかに、数年前だけでも私は気付かなかった。これは別のものです。これは私と同様のアプローチを示しており、この目的に適していると思います。

関連情報