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프로세스가 호출되며 다시 불완전한 개수를 얻게 됩니다. 이 문제를 해결하는 한 가지 방법은 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적어도 제공한 예에서는 작동했습니다. 저는 정규식 마법사가 아니므로 어떤 경우에는 문제가 발생할 수 있습니다. 시도해 보시고 효과가 있는지 알려주세요!

관련 정보