awkを使用して複数のファイルを処理するには、パターンの後の変数の発生回数を計算する必要があります。各ファイルの後にアレイのリセットを停止する方法は?

awkを使用して複数のファイルを処理するには、パターンの後の変数の発生回数を計算する必要があります。各ファイルの後にアレイのリセットを停止する方法は?

ディレクトリに特定の拡張子を持つファイルの場合は、パターンの後の括弧内のすべての変数の発生回数を計算したいと思います。各ファイルには、複数のレコード/行のパターンを含めることができます。

これまでは、ファイルを処理して結果を配列に保存できますが、処理するすべての新しいファイルが配列を上書きしているようです。配列値を保持する方法は?

#!/bin/bash
for x in `find . $PROGFILES -name "*.fgl"`
do

    awk -f <(cat -  <<-'EOF'
        / envget | env-get | \"envget\" | \"env-get\" /  
        {
        gsub( /get-env/, "envget")              ;# removes hypens
        gsub( /.*envget/, " envget")
        gsub( "\\concat" ,"")       ;# removes concat
        gsub( "\\substring" , "")   ;# removes substring
        for (i = 1; i<= NF; i++) {
            if ( substr( $i, 1, 6) == "envget" ) {
                    lenofget = 8;
                } else {
                    lenofget = 0;
                }
                if ( lenofget != 0 ) {
                    gsub("\\envget" , "",$i)    ;#removes envget
                    gsub ( /\)\.*/, "",$i)      ;#removes everything after a closing parenthesis
                    gsub ( /\47/, "",$i)        ;#so used octal instead
                    gsub ( /\(/, "",$i)         ;#removes paraentheses
                    gsub ( /\"/, "",$i)         ;#removes double quotes
                    gsub ( /\,.*/, "",$i)       ;#removes everything after a , This is for any concat syntax
                    gsub ( /[\/].*/, "",$i)     ;#removes everything after a forward slash
                    narr[$i]++
                }
            }
        }
        END {
            for (y in narr) {
                printf("%s - %d\n",y, narr[y])

            }   
        }   
EOF
) $x
done

パターン付きファイルの一般的なレコード/行は次のとおりです。

if envget("SYPSDATA") in {SPACES "."}
    set lf-path = "envget"('SYPSCTRL')
if env-get(concat("LOG_PRINTER",service-centre)) != spaces
trconcat(env-get("TMPDIR"),"/ps_xxx_temp.psv")
envget(substring(ws-envprinter1,1,strlen(ws-envprinter1)))
      set lf-path = "envget"('SYPSCTRL')
            display bitmap concat(envget('BTS')'/images/repedge.gif') @19,44

複数のパターン一致行を持つ複数のファイルがあることを考えると、次のような出力を取得したいと思います(ここでは、数字は各ファイルで見つかった合計数です)。

BTS - 15
LOG_PRINTER - 7
ws-envprinter1 - 3
SYPSDATA - 120
TMPDIR - 130
SYPSCTRL - 200

答え1

あなたはやっています

「検索」でxについて。 $PROGFILES - 名前 "*.fgl"`
する
    アッ(awk_プログラム)$x
完璧
awk各ファイルに対して新しいプロセスを開始します。なぜ?ただ

アッ(awk_プログラム)*.fgl "$PROGFILES"/*.fgl

サブディレクトリを検索する必要がない場合。本当にサブディレクトリを検索する必要がある場合は、少し複雑です。

探す。 "$PROGFILES" - 名前 "*.fgl" -exec awk(awk_プログラム){}+

メモ:

  • 妥当な理由がなく、実行している操作を明確に知らない限り、常にシェル変数(および"$PROGFILES")を引用する必要があります。"$x"
  • これを使用する必要はありませんcat。 awkプログラムを引用符で囲むことができます:

    awk '
            / envget | env-get | \"envget\" | \"env-get\" /  
            {
                gsub( /get-env/, "envget")
            }
        ' "$x"
    

    またはファイルに入れて 。awk -f (awk_program_file)

  • コマンドラインサイズに(非常に大きい)制限があるため、上記の方法のいずれも合計数を取得することは保証されていません。結合された名前がその制限を超えるファイルが多すぎると、そのファイルをすべて処理するために複数のfindプロセスawkが呼び出され、再度不完全な数が得られます。この問題を解決する1つの方法は、awk個々の実行の結果を収集して組み合わせることです。

答え2

あなたの試みにいくつかのエラーがあります(自慢しているわけではありません。私たちは皆学ぶためにここにいます!)。

各呼び出しは独自のメモリ空間を持つ別のプロセスなので、ファイルが処理されると、次の呼び出しawkで配列の値を保持しないのが正常です。awk繰り返しごとにカウントを出力しfor、最後に追加の手順を実行してすべてを要約する必要があります。最も簡単な方法は、これらすべてをファイルに追加することです。

#!/bin/bash

echo "" > "$HOME/tmp_count.txt"

for x in `find . $PROGFILES -name "*.fgl"`
do

    awk '
        /env-?get/  {
          for (i = 1; i<= NF; i++) {
            if ($i ~ /env-?get/) {
              a = gensub(/.*env-?get\"?\((concat\(|substring\()?(\"|\47)?([a-zA-Z0-9\-_]*)(\"|\47)? *(\)|,)?.*/, "\\3", $i)
              arr[a]++
            }
          }
        }
        END {
            for (y in arr) {
                printf("%s %d\n",y, arr[y])
            }   
        }
        ' "$x" >> "$HOME/tmp_count.txt"
done

awk '{arr[$1] += $2}END{for (key in arr) {printf("%s - %d\n", key, arr[key])}}' < "$HOME/tmp_count.txt"

また、あなたの方法が常に動作するわけではないようで、aで大きな正規表現を試してみgensubました。私は正規表現ウィザードではないので、場合によっては問題が発生する可能性があります。試してみて、効果があるか教えてください!

関連情報