특정 열을 이름으로 인쇄하는 방법은 무엇입니까?

특정 열을 이름으로 인쇄하는 방법은 무엇입니까?

다음 파일이 있습니다.

id  name  age
1   ed    50
2   joe   70   

id나는 단지 인쇄 와 칼럼을 원합니다 age. 이제는 다음을 사용합니다 awk.

cat file.tsv | awk '{ print $1, $3 }'

그러나 이를 위해서는 열 번호를 알아야 합니다. 열 번호 대신 열 이름(첫 번째 줄에 지정)을 사용할 수 있는 방법이 있습니까?

답변1

어쩌면 다음과 같은 것일 수도 있습니다.

$ cat t.awk
NR==1 {
    for (i=1; i<=NF; i++) {
        ix[$i] = i
    }
}
NR>1 {
    print $ix[c1], $ix[c2]
}
$ awk -f t.awk c1=id c2=name input 
1 ed
2 joe
$ awk -f t.awk c1=age c2=name input 
50 ed
70 joe

명령줄에 인쇄할 열을 지정하려면 다음을 수행할 수 있습니다.

$ cat t.awk 
BEGIN {
    split(cols,out,",")
}
NR==1 {
    for (i=1; i<=NF; i++)
        ix[$i] = i
}
NR>1 {
    for(i=1; i <= length(out); i++)
        printf "%s%s", $ix[out[i]], OFS
    print ""
}
$ awk -f t.awk -v cols=name,age,id,name,id input 
ed 1 ed 50 1 
joe 2 joe 70 2 

( -v블록에 정의된 변수를 가져오기 위한 스위치에 유의하세요 BEGIN.)

답변2

csvkit

입력 데이터를 csv 형식으로 변환하고 csv 도구를 사용합니다.csvcut에서 csvkit:

$ cat test-cols.dat 
id  name  age
1   ed    50
2   joe   70 

csvkit을 설치합니다:

$ pip install csvkit

trsqueeze 옵션과 함께 사용하여 -s유효한 csv 파일로 변환하고 적용합니다 csvcut.

$ cat test-cols.dat | tr -s ' ' ',' | csvcut -c id,age
id,age
1,50
2,70

이전 데이터 형식으로 되돌리려면 다음을 사용할 수 있습니다.tr ',' ' ' | column -t

$ cat test-cols.dat | tr -s ' ' ',' | csvcut -c id,age | tr ',' ' ' | column -t
id  age
1   50
2   70

노트

  • csvkit은 또한 다양한 구분 기호(공유 옵션 -d또는 --delimiter), 그러나 csv 파일을 반환합니다.

    • 파일이 열을 구분하기 위해 공백만 사용하는 경우(탭이 전혀 없음) 다음이 작동합니다.

      $ csvcut -d ' ' -S -c 'id,age' test-cols.dat
      id,age
      1,50
      2,70
      
    • 파일이 탭으로 구분된 열을 사용하는 경우 다음이 작동하고csvformatTSV 파일을 다시 가져오는 데 사용할 수 있습니다.

      $ csvcut -t -c 'id,age' test-cols.dat | csvformat -T
      id  age
      1   50
      2   70
      

      제가 확인해본 결과 탭은 하나만 허용됩니다.

  • csvlook테이블은 Markdown 테이블 형식으로 포맷될 수 있습니다.

    $ csvcut -t -c "id,age" test-cols.dat | csvlook
    | id | age |
    | -- | --- |
    |  1 |  50 |
    |  2 |  70 |
    
  • UUOC(쓸모없는 고양이): 나는 이런 식으로 명령을 구성하는 것을 좋아합니다.

답변3

그냥 Perl 솔루션을 더미 위에 던져보세요:

#!/usr/bin/perl -wnla

BEGIN {
    @f = ('id', 'age');   # field names to print
    print "@f";           # print field names
}

if ($. == 1) {            # if line number 1
    @n = @F;              #   get all field names
} else {                  # or else
    @v{@n} = @F;          #   map field names to values
    print "@v{@f}";       #   print values based on names
}

답변4

가격 대비 좋은 가치. 선택한 출력 순서에 관계없이 소스의 열 수와 인쇄할 열 수를 처리할 수 있습니다.

예를 들어. 부르다:script-name id age

outseq=($@)
colnum=($( 
  for ((i; i<${#outseq[@]}; i++)) ;do 
    head -n 1 file |
     sed -r 's/ +/\n/g' |
      sed -nr "/^${outseq[$i]}$/="
  done ))
tr ' ' '\t' <<<"${outseq[@]}"
sed -nr '1!{s/ +/\t/gp}' file |
  cut -f $(tr ' ' ','<<<"${colnum[@]}") 

산출

id      age
1       50
2       70

관련 정보