3

私はシェル スクリプトを使用しており、その中で awk スクリプトを使用しています。awkオプションを使用してシェルスクリプトからパラメータを渡してい-vます。ある時点で、引数のサイズが特定の制限を超えると、「引数リストが長すぎます」というエラーが発生しました。これは私の以前の質問でしたが、同じ根本的な原因を見つけました。今私の質問は:

-vオプションを使用してシェルからawkに渡される変数=大きすぎる⟶したがって、引数リストが長すぎるエラーを取得しています

awk私の考えは、大きな変数を小さなチャンクに分割して配列に格納し、単一の変数を に渡す代わりに、配列をに渡すことawkです。

私の質問は:

  • 大きな変数を小さな配列に分割してから、に戻すことは可能ですかawk? awkスクリプト内でシェルの変数を変更する方法を知っています。awkしかし、スクリプト内のシェルの配列を変更するにはどうすればよいでしょうか?

-v オプションはお勧めできないと読み、変数値をパイプすることを提案しました。だからもしそうだったら

echo variable | awk '{}' 

したがって、変数はパイプされます。しかし、他の変数と一緒に配列をパイプする必要があります。手伝っていただけませんか?

 CODE DESCRIPTION
 addvariable=""
 export variable
 loop begins
 eval $(awk -v tempvariable="$addvariable" '{tempvariable=tempvariable+"long string"  variable=tempvariable(Here is where the shell variable(variable) is being modified )}')

  In shell
  addvariable=$variable (Taking the new value of shell variable and feeding back to awk in the next iteration)
   loop ends

したがって、問題は addvariable と variable が増加し続けるため、引数が長すぎるというエラーが発生することです..だから私がしなければならないことは、tempvariable を小さなチャンクに分割してから variable[1] variable[2] に格納することですなど、それを addvariable[1]、addvariable[2] とフィード addvariable[1]、[2] に割り当てます。awk内のビッグデータを変数[1]変数[2]に保存する方法

CODE addshellvariable=""

for i in {0..10}
{
zcat normalfile{i} > FILE A
zcat hugefile{i} > FILE

export shellvariable=""
getdate=grep "XXX" FILE B|sort|Uniq (getdate contains a list of id's)
eval $(awk -v getdata="$getdata" -v addshellvariable="$addshellvariable" BEGIN {tempvariable="";split(addshellvariable,tempshellvariableArray,"*");while(t <= length(tempshellvariable)) {awkarray[tempshellvariableArray[t]];} {for(id in ids) {awkarray[id];} END {for(id in awkarray) {tempvariable=tempvariable"*"id"*"awkarray[id]}  **print "shellvariable"=tempvariable;**}} FILE A)

  addshellvariable=$shellvariable;
}

ご覧のとおり、シェル内に awk が埋め込まれています。awkarray コンテンツを awk に再度フィードバックする必要があるたびに..更新されたものを取得できるようにするため、それを印刷してシェル変数で awk 配列コンテンツを取得している理由です。別のシェル変数「addshellvariable」に格納され、次の反復で awk に渡されます。しかし問題は、シェル変数のサイズが特定のポイントを超えると、 Argument too long エラーが発生することです。したがって、
print "shellvariable"=tempvariable;を実行する代わりに、次のような方法で解決策が必要でした。print "shellvariable[1]"=A part of tempvariable; として作成できます。等々 ...

4

1 に答える 1

3

あなたの殻はあなたを制限しているようです。あなたの推測は正しいと思います。これは awk の問題ではなく、awk を呼び出しているスクリプト言語です。

ファイルからロードされた変数で awk をプリロードできます。これをチェックしてください:

$ printf 'foo=2\nbar=3\nbaz=4\n' > vars
$ printf 'snarf\nblarg\nbaz\nsnurry\n' > text
$ awk 'NR==FNR{split($0,a,"=");vars[a[1]]=a[2];next} $1 in vars {print vars[$1]}' vars text
4
$

これはどのように作動しますか?

最初の 2 つの printf 行で生データが得られます。それらが完全に明確でない場合は、リダイレクトなしで実行します (または結果のファイルを cat します)。

awk スクリプトには 2 つの主要なセクションがあります。awk スクリプトは、 の繰り返しで構成されますcondition { commands }。この場合、これらのセットが 2 つあります。

最初のセットの条件はNR==FNRです。これは、awk が処理している現在のレコード番号 (NR) が現在のファイルの現在のレコード番号と同じ場合、「true」と評価されます。明らかに、これは FIRST ファイルに対してのみ機能します。これは、2 番目のファイルの最初の行の時点で、NR が 1 に最初のファイルの行数を加えたものであるためです。

このセクション内でsplit()、等号に従って行を作成し、データを という配列に入れますvars

2 番目のセットには の条件が$1 in varsあり、現在の行の最初の単語がvars配列の添字として存在する場合に true と評価されます。これらの変数で何を達成しようとしているのかわからないので、これは vars でできることの例としてのみ含めています。

これで問題は解決しますか? そうでない場合は、修正方法を理解するためにコードの一部を確認する必要があります。


コメントの提案ごとに更新してください。これは、大きな変数に対して機能することの証明です。

まず、入力データを準備します。

$ dd if=/dev/random of=out.rand count=128k bs=1k
131072+0 records in
131072+0 records out
134217728 bytes transferred in 3.265765 secs (41098404 bytes/sec)
$ b64encode -o out.b64 out.rand out.rand
$ ls -lh out.b64
-rw-r--r--  1 ghoti  wheel   172M Jul 17 01:08 out.b64
$ awk 'BEGIN{printf("foo=")} NR>1{printf("%s",$0)} END{print ""}' out.b64 > vars
$ ls -lh vars
-rw-r--r--  1 ghoti  wheel   170M Jul 17 01:10 vars
$ wc -l vars
       1 vars
$ cut -c1-30 vars
foo=orq0UgQJyUAcwJV0SenJrSHu3j

わかりました、1 行に ~170MB の変数があります。それを awk に吸い込みましょう。

$ awk 'NR==FNR{split($0,a,"=");vars[a[1]]=a[2];next} END{print length(vars["foo"]);print "foo=" substr(vars["foo"],0,26);}' out.var bar
178956971
foo=orq0UgQJyUAcwJV0SenJrSHu3j

変数のサイズを見ることができ、最初の 26 文字はシェルから見たものと一致します。うん、それは動作します。

于 2012-07-17T03:35:12.347 に答える