2013-04-18 9 views
4
를 사용하여 이름으로 CSV 필드를 따기

가정하자 나는 CSV는 다음과 같은 형식의 헤더 파일이 있습니다는 AWK

Field1,Field2 
3,262000 
4,449000 
5,650000 
6,853000 
7,1061000 
8,1263000 
9,1473000 
10,1683000 
11,1893000 

I 필드의 쉼표로 구분 된 목록을 것 awk 스크립트를 작성하려합니다 이름이 target 인 경우이를 배열로 분할 한 다음 지정한 이름의 열만 선택하십시오.

이것은 지금까지 시도한 것으로, head 배열에 원하는 헤더가 있고 targets 배열에 주어진 명령 줄에서 전달되는 원하는 대상이 포함되어 있는지 확인했습니다. 내가 명령으로이 스크립트를 호출 할 때

BEGIN{ 
    FS="," 
    split(target, targets, ",") 

} 

NR==1 { 
    for (i = 1; i <= NF; i++) head[i] = $i 
} 

NR !=1{ 
    for (i = 1; i <= NF; i++) { 
     if (head[i] in targets){ 
      print $i 
     } 
    } 
} 

AWK -v 대상 = 필드 1 -f GetCol.awk Debug.csv는

나는 인쇄 아무것도 얻을 수 없다.

답변

8

다른 사람들이 같은 문제에 부딪혔을 때를 대비하여 알아 냈습니다.

배열 구성원 테스트에 사용하는 in 키워드와 관련이 있습니다. 이 키워드는 왼쪽에있는 피연산자가 값 대신에 인 인덱스 중 하나인지 여부 만 테스트합니다. 수정 사항은 다음과 같이 역방향 조회 배열을 만드는 것입니다.

BEGIN{ 
    OFS=FS="," 
    split(target, t_targets, ",") 
    for (i in t_targets) 
     targets[t_targets[i]] = i 
} 
+0

+1 직접 알아내는 중! 작업에 전체 스크립트를 추가 했으므로 도움이 될 수 있습니다. –

5

내 두 센트 :

BEGIN{ 
    OFS=FS="," 
    split(target,fields,FS)   # We just set FS don't hard the comma here 
    for (i in fields)     # Distinct var name to aviod headaches 
     field_idx[fields[i]] = i  # Reverse lookup 
} 
NR==1 {        # Process header 
    for (i=1;i<=NF;i++)    # For each field header 
     head[i] = $i     # Add to hash for comparision with target 
    next        # Skip to next line 
} 
{          # Don't need invert condition (used next) 
    sep=""        # Set for leading separator 
    for (i=1;i<=NF;i++)    # For each field 
     if (head[i] in field_idx) { # Test for current field is a target field 
      printf "%s%s",sep,$i  # Print the column if matched 
      sep=OFS     # Set separator to OFS     
    } 
    printf "\n"      # Print newline character 
} 
1

@ sudo_O의 솔루션의 확장 (감사합니다)

    명령 줄 인수를 기반으로 표준 입력에서
  1. 출력 필드,
  2. 그 요청 된 순서대로 필드를 출력합니다 (가능하면 여러 번).
  3. 은 쉼표를 출력합니다. lder 필드가 요청되었지만 찾을 수 없을 때
  4. 헤더의 중복 필드 이름에 대한 표준 오류가 경고됩니다.
#!/usr/bin/awk -f 
# Process standard input outputting named columns provided as arguments. 
# 
# For example, given foo.dat containing 
#  a b c c 
#  1a 1b 1c 1C 
#  2a 2b 2c 2C 
#  3a 3b 3c 3C 
# Running 
# cat foo.dat | ./namedcols c b a a d 
# will output 
# 1c 1b 1a 1a d 
# 2c 2b 2a 2a d 
# 3c 3b 3a 3a d 
# and will warn on standard error that it 
# Ignored duplicate 'c' in column 4 
# Notice that the requested but missing column d contains "d". 
# 
# Using awk's -F feature it is possible to parse comma-separated data: 
# cat foo.csv | ./namedcols -F, c b a a d 
BEGIN { 
    for (i=1; i<ARGC; ++i) 
     desired[i] = ARGV[i] 
    delete ARGV 
} 
NR==1 { 
    for (i=1; i<=NF; i++) 
     if ($i in names) 
      printf "Ignored duplicate '%s' in column %d\n", $i, i | "cat 1>&2" 
     else 
      names[$i] = i 
    next 
} 
{ 
    for (i=1; i<ARGC; ++i) 
     printf "%s%s",           \ 
       (i==1 ? "" : OFS),        \ 
       ((ndx = names[name = desired[i]])>0 ? $ndx: name) 
    printf RS 
}