AWK 및 CSV 파일 이해

Oct 20 2020

CSV 파일의 필드 목록을 분석하고 지정된 필드에있는 각기 다른 문자열의 수를 계산하고 발견 된 각 문자열의 수를 출력하는 AWK 프로그램을 어떻게 작성할 수 있습니까? 저는 C와 Java로만 코딩했기 때문에 AWK 구문에 대해 완전히 혼란 스럽습니다. 나는 가장 단순한 개념을 이해하지만 AWK는 구조가 훨씬 다릅니다. 언제든지 감사합니다, 감사합니다!

BEGIN {
    FS = ""
}
{
    for(i = 1; i <= NF; i++) 
        freq[$i]++
    PROCINFO ["sorted_in"] = "@val_num_desc" #this got the desired result
}
END {
    for {this in freq) 
        printf "%s\t%d\n", this, freq[this]
}

다음을 포함하는 CSV 파일 :

Field1, Field2, Field3, Field4
A, B, C, D
A, E, F, G
Z, E, C, D
Z, W, C, Q

결과를 얻을 수 있습니다.

A     2
B     1
C     3
Q     1
D     1
E     2
F     1
,     12
G     1
W     1
Field1,Field2,Field3,Field4     1
Z     2

이것은 원하는 결과입니다.

A       10
C       7
D       2
E       2
Z       2
B       1
Q       1
Field1  1
Field2  1
F       1
Field3  1
G       1
Field4  1
W       1

주석이 달린 내 코드에 대한 편집이 있습니다.

답변

1 JamesBrown Oct 21 2020 at 03:35

코드 수정 :

$ awk ' BEGIN { # you need BEGIN block for FS FS = ", *" # your data had ", " and "," seps } # ... based on your sample output { for(i = 1; i <= NF; i++) freq[$i]++
}
END {
    for(this in freq)                       # fixed a parenthesis
        printf "%s\t%d\n", this, freq[this]
}' file

출력 (GNU awk 사용. 다른 awks는 다른 순서로 출력을 표시 함) :

A       2
B       1
C       3
Q       1
D       2
Field1  1
E       2
Field2  1
F       1
Field3  1
G       1
Field4  1
W       1
Z       2
StevenPenny Oct 21 2020 at 03:10

AWK는 실제로이 작업에 적합한 도구가 아닙니다. AWK는 쉼표 또는 탭으로 구분 된 데이터를 해석 할 수 있지만 필드 엔클로저 또는 이스케이프 개념이 없습니다. 따라서 다음과 같은 간단한 예를 처리 할 수 ​​있습니다.

Month,Day
January,Sunday
February,Monday

그러나이 유효한 예에서는 실패합니다.

Month,Day
January,"Sunday"
February,"Monday"

그렇기 때문에 다른 언어를 고려하는 것이 좋습니다. 파이썬과 같은 것 :

import csv
o = open('a.csv')
for m in csv.DictReader(o):
   print(m)

https://docs.python.org/library/csv.html

또는 Ruby :

require 'csv'
CSV.table('a.csv').each do |m|
   p m
end

https://ruby-doc.org/stdlib/libdoc/csv/rdoc/CSV.html

또는 PHP :

<?php
$r = fopen('a.csv', 'r'); $a_head = fgetcsv($r); while (true) { $a_row = fgetcsv($r); if (feof($r)) {
      break;
   }
   $m_row = array_combine($a_head, $a_row); print_r($m_row);
}

https://php.net/function.fgetcsv