web-dev-qa-db-ja.com

POSIXシェルスクリプトで疑似配列を使用する方法

POSIXシェルスクリプトで疑似配列を使用する方法

Bashスクリプトの10個の整数の配列を、POSIXシェルスクリプトと同様のsomethingに置き換えます。

なんとか Rich’s sh(POSIX Shell)tricks 、セクションWorking with arrayに遭遇しました。

私が試したこと:

save_pseudo_array()
{
    for i do
        printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
    done
    echo " "
}

coords=$(save_pseudo_array "$@")
set -- 1895 955 1104 691 1131 660 1145 570 1199 381
eval "set -- $coords"

私はそれを理解していません、それが問題です、誰かがそれにいくつかの光を当てることができれば、大歓迎です。

6

アイデアは、後でリストまたは任意の文字列を再構築するために使用できる形式で、任意の文字列のリストをスカラー変数にエンコードすることです。

 $ save_pseudo_array x "y z" $'x\ny' "a'b"
'x' \
'y z' \
'x
y' \
'a'\''b' \

$

その前にset --を付けると、xy z文字列のリストを再構築して$@配列に格納するシェルコードが作成されます。 evaluateする必要があります。

sedは、各文字列を適切に引用します(最初の行の最初、最後の行の終わりに'を追加し、すべての''\''に置き換えます)。

ただし、これは、引数ごとに1つのprintfおよびsedコマンドを実行することを意味するため、かなり非効率的です。これは、1つのawk呼び出しだけで、より簡単な方法で実行できます。

save_pseudo_array() {
  LC_ALL=C awk -v q=\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q "\\" q q, ARGV[i])
        printf "%s ", q ARGV[i] q
      }
      print ""
    }' "$@"
}
8

基本的な考え方は、setを使用して、配列からインデックス付きの値を操作するエクスペリエンスを再現することです。したがって、配列を操作したい場合は、代わりに値を指定してsetを実行します。それは

set -- 1895 955 1104 691 1131 660 1145 570 1199 381

次に、$1$2forなどを使用して、指定された値を処理します。

ただし、複数のアレイが必要な場合は、あまり役に立ちません。そこにsaveevalのトリックがあります: Richのsave関数 ¹は現在の位置パラメーターを処理し、適切な引用符で文字列を出力します。これをevalと一緒に使用して、格納された値を復元できます。したがって、あなたは走る

coords=$(save "$@")

現在機能している配列をcoordsに保存してから、新しい配列を作成し、それを処理します。coordsを再び処理する必要がある場合は、evalを使用します。

eval "set -- $coords"

この例を理解するには、ここで2つの配列(以前に値が設定され、coordsに格納されている配列)と1895、955などを含む配列を使用していることを考慮する必要があります。スニペット自体はそれだけではそれほど意味がありません。set行とeval行の間で処理が行われます。後で1895、955アレイに戻る必要がある場合は、coordsを復元する前に、まずそれを保存します。

newarray=$(save "$@")
eval "set -- $coords"

こうすると、復元できます$newarray後で。


asとして定義

save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
9
Stephen Kitt