디렉토리에 특정 확장자를 가진 파일의 경우 패턴 뒤의 괄호 안에 있는 모든 변수의 발생 횟수를 계산하고 싶습니다. 각 파일에는 여러 레코드/라인의 패턴이 포함될 수 있습니다.
지금까지는 파일을 처리하고 결과를 배열에 저장할 수 있지만 처리하는 모든 새 파일이 배열을 덮어쓰는 것 같습니다. 배열 값을 유지하는 방법은 무엇입니까?
#!/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
적어도 제공한 예에서는 작동했습니다. 저는 정규식 마법사가 아니므로 어떤 경우에는 문제가 발생할 수 있습니다. 시도해 보시고 효과가 있는지 알려주세요!