탭을 필드 구분자로 사용하여 awk 내부 정렬

탭을 필드 구분자로 사용하여 awk 내부 정렬

헤더를 유지하면서 탭으로 구분된 파일을 특정 필드별로 정렬하고 싶습니다. awk여기에 설명된 대로 사용하고 있습니다.awk에서 정렬 및 고유sort, 그러나 필드 구분 기호가 탭임을 누구에게 알릴 수 있는지 알 수 없습니다 .

장난감 데이터:

$ echo -e "head_1\thead_2\thead_3" > file.tsv
$ echo -e "aaa zzz\tc\t300" >> file.tsv
$ echo -e "bbb yyy ooo\ta\t100" >> file.tsv
$ echo -e "ccc xxx nnn\tb\t200" >> file.tsv
$ column -ts $'\t' file.tsv
head_1       head_2  head_3
aaa zzz      c       300
bbb yyy ooo  a       100
ccc xxx nnn  b       200

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2" }' file.tsv | column -ts $'\t' 
head_1       head_2  head_3
ccc xxx nnn  b       200           ## note these data are sorted 
bbb yyy ooo  a       100           ## based on the xxx/yyy/zzz 
aaa zzz      c       300           ## not the a/b/c

sort필드 구분 기호가 탭임을 명시적으로 알리려고 하면 다음 오류가 발생합니다. 이는 인용 문제와 관련이 있다고 생각됩니다.

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t $'\t'" }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

sort`awk 내부 에 대한 열 구분 기호를 어떻게 지정합니까 ? 감사해요

SE의 웹 인터페이스는 Notepad++보다 구문 강조 작업을 더 잘 수행합니다. 제가 시도한 몇 가지 사항은 다음과 같습니다.

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t $'$'\t''" }' file.tsv | column -ts $'\t'
head_1       head_2  head_3
aaa zzz      c       300
bbb yyy ooo  a       100
ccc xxx nnn  b       200


$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t $'\t'" }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t "'$'\t''"" }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

$ awk -F'\t' 'NR==1; NR>1 { print | "sort -k2 -t "'$'\t'' }' file.tsv | column -ts $'\t'
sort: option requires an argument -- 't'
Try 'sort --help' for more information.
head_1  head_2  head_3

답변1

다음 옵션 중 하나를 선택했습니다.

... | "sort -k2 -t \\\t "
... | "sort -k2 -t \"\t\" "
... | "sort -k2 -t'\''\t'\'' "
... | "sort -k2 -t \047\011\047" ## preferred 

\011에 대한 옥텟 ASCII 코드입니다.문자/ \047작은따옴표 '

awk -v q="'" ... { print | "sort -k2 -t " q "\t" q }'
awk -v tb="'\t'" ... { print | "sort -k2 -t " tb }'
awk -v tb=$'\t' ... { print | "sort -k2 -t \"" tb "\"" }'
awk -v tb=$'\t' -v q="'" ... { print | "sort -k2 -t " q tb q }'

그리고 더 많은 …; 읽다awk의 쉘 인용 문제; 또한보십시오awk의 이스케이프 시퀀스

답변2

이것은 적절한 한 줄짜리 방법이 아닐 수도 있지만 간단하고 탭 문자를 사용할 필요가 없습니다... :D

var=$(head -1 file.tsv);perl -ne '{ print $_ if $. > 1; }'  file.csv| sort -k2 | sed "1 i $var" | column -ts "\t"

답변3

FWIW 다음은 데이터를 정렬하지만 헤더를 맨 위에 유지하는 실제 문제를 해결하는 방법입니다.

awk -v OFS='\t' '{print (NR>1), $0}' file.tsv | sort -t$'\t' -k1,1n -k3 | cut -f2-

위의 작업은 입력 데이터 앞에 0 또는 1을 추가하여 작동합니다(첫 번째 줄은 0, 다른 모든 줄은 1). 먼저 해당 표시기를 정렬한 다음 관심 있는 실제 키를 정렬한 다음 추가된 필드를 다시 제거하면 됩니다. .

단계별로 작업하는 방법은 다음과 같습니다.

$ awk -v OFS='\t' '{print (NR>1), $0}' file.tsv
0   head_1  head_2  head_3
1   aaa zzz c   300
1   bbb yyy ooo a   100
1   ccc xxx nnn b   200

$ awk -v OFS='\t' '{print (NR>1), $0}' file.tsv | sort -t$'\t' -k1,1n -k3
0   head_1  head_2  head_3
1   bbb yyy ooo a   100
1   ccc xxx nnn b   200
1   aaa zzz c   300

$ awk -v OFS='\t' '{print (NR>1), $0}' file.tsv | sort -t$'\t' -k1,1n -k3 | cut -f2-
head_1  head_2  head_3
bbb yyy ooo a   100
ccc xxx nnn b   200
aaa zzz c   300

관련 정보