awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}' file
산출
$ more file
0 1 2
3 4 5
6 7 8
9 10 11
$ ./shell.sh
0 3 6 9
1 4 7 10
2 5 8 11
10000 라인 파일에서 Jonathan의 Perl 솔루션에 대한 성능
$ head -5 file
1 0 1 2
2 3 4 5
3 6 7 8
4 9 10 11
1 0 1 2
$ wc -l < file
10000
$ time perl test.pl file >/dev/null
real 0m0.480s
user 0m0.442s
sys 0m0.026s
$ time awk -f test.awk file >/dev/null
real 0m0.382s
user 0m0.367s
sys 0m0.011s
$ time perl test.pl file >/dev/null
real 0m0.481s
user 0m0.431s
sys 0m0.022s
$ time awk -f test.awk file >/dev/null
real 0m0.390s
user 0m0.370s
sys 0m0.010s
편집 Ed Morton (@ ghostdog74 당신이 승인하지 않으면 자유롭게 삭제하십시오).
좀 더 명시적인 변수 이름이있는이 버전은 아래 질문에 대한 답을 얻고 일반적으로 스크립트가 수행하는 작업을 명확히하는 데 도움이 될 것입니다. 또한 OP가 원래 요청한 구분 기호로 탭을 사용하므로 빈 필드를 처리하고 우연히이 특정 경우에 대해 출력을 약간 예쁘게 만듭니다.
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{
for (rowNr=1;rowNr<=NF;rowNr++) {
cell[rowNr,NR] = $rowNr
}
maxRows = (NF > maxRows ? NF : maxRows)
maxCols = NR
}
END {
for (rowNr=1;rowNr<=maxRows;rowNr++) {
for (colNr=1;colNr<=maxCols;colNr++) {
printf "%s%s", cell[rowNr,colNr], (colNr < maxCols ? OFS : ORS)
}
}
}
$ awk -f tst.awk file
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
위의 솔루션은 모든 awk에서 작동합니다 (물론 오래된 깨진 awk 제외-YMMV).
위의 솔루션은 전체 파일을 메모리로 읽습니다. 입력 파일이 너무 크면 다음을 수행 할 수 있습니다.
$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ printf "%s%s", (FNR>1 ? OFS : ""), $ARGIND }
ENDFILE {
print ""
if (ARGIND < NF) {
ARGV[ARGC] = FILENAME
ARGC++
}
}
$ awk -f tst.awk file
X row1 row2 row3 row4
column1 0 3 6 9
column2 1 4 7 10
column3 2 5 8 11
거의 메모리를 사용하지 않지만 한 줄의 필드 수당 한 번 입력 파일을 읽으므로 전체 파일을 메모리로 읽는 버전보다 훨씬 느립니다. 또한 필드의 수는 각 라인에서 동일하고 용 GNU AWK를 사용하는 가정 ENDFILE
하고 ARGIND
있지만 AWK가 테스트와 동일한 기능을 수행 할 수 있습니다 FNR==1
와 END
.