많은 수의 열을 재정렬하는 방법은 무엇입니까?

많은 수의 열을 재정렬하는 방법은 무엇입니까?

나는 많은 수의 열을 재정렬하기 위해 파이프 가능한 단일 라이너를 찾고 있습니다(예 awk를 들어 명령 에 열 번호를 수동으로 입력하는 것은 awk '{print $3,$2,$1}'불가능합니다). 순서는 정렬 체계(알파벳순, 숫자순 - '정렬'과 비슷하지만 행이 아닌 열에 적용됨)에 따라 지정되거나 텍스트 파일에 임의로 지정될 수 있습니다.

답변1

Perl을 사용한 간단한 솔루션.

먼저 값 배열을 채웁니다.

➜ ~ x="$(cat << END
22      79      83      16      25      1       4       82      34      68
48      43      2       26      39      2       71      43      57      41
77      70      73      18      76      33      21      54      67      50
6       65      46      92      25      70      53      28      3       40
32      60      76      39      26      44      34      91      24      39
59      75      96      85      52      98      69      28      72      94
48      0       88      55      6       78      1       54      83      81
3       43      48      24      23      87      28      98      38      67
97      73      74      24      92      67      1       27      90      85
32      55      52      44      26      37      87      37      100     92
END
)"
➜  ~ perl -lane '@i=sort({ @F[$a] <=> @F[$b] } 0..$#F) if $.==1; 
                 print join("\t", @F[@i])' <<< "$x"      

1       4       16      22      25      34      68      79      82      83
2       71      26      48      39      57      41      43      43      2
33      21      18      77      76      67      50      70      54      73
70      53      92      6       25      3       40      65      28      46
44      34      39      32      26      24      39      60      91      76
98      69      85      59      52      72      94      75      28      96
78      1       55      48      6       83      81      0       54      88
87      28      24      3       23      38      67      43      98      48
67      1       24      97      92      90      85      73      27      74
37      87      44      32      26      100     92      55      37      52

  • -a@F: 배열을 자동으로 채우는 자동 분할을 활성화합니다.
  • -n: while 루프의 각 줄을 읽습니다.
  • $#F: 배열에서 가장 큰 0 기반 인덱스를 반환합니다.
  • <=>: 정렬 기능을 위한 비교 연산자(숫자 입력만 가능, 문자열 비교에는 사용 cmp)
  • sort: 배열에서 정렬된 인덱스를 반환합니다 0..$#F(내장 $a$b변수 사용).
  • @i@F: (이 예에서는 @i = 5 6 3 0 4 8 9 1 7 2) 에 대한 정렬된 인덱스 배열을 포함합니다.
  • $. == 1: 첫 번째 줄에서만 수행하십시오.
  • @F[@i]: 정렬된 인덱스를 기준으로 각 행을 정렬합니다.

원천:https://learnbyexample.gitbooks.io/command-line-text-processing/content/perl_the_swiss_knife.html

답변2

스트리밍 가능한 솔루션은 다음과 같습니다.

열의 첫 번째 행을 기준으로 정렬하고, 그렇지 않으면 다른 곳에서 정렬 키를 가져오도록 조정한다고 가정합니다.

정렬 키 생성(Rush 배열 재사용):

echo -e  "b a c\n5 4 6\n8 7 9" > data

key=$(head -n1 data | sed 's/ \+/\n/g' | nl -n ln | sort -k2 | cut -f1)
    

$key현재 다음을 보유하고 있습니다.

2
1
3

이제 키를 사용하여 열을 정렬합니다.

awk -v key="$key" '
BEGIN { split(key, order, "\n") }

{ 
  for(i=1; i<=length(order); i++) { 
    printf("%s ", $order[i])
  }
  printf("\n");
}' data

산출:

a b c 
4 5 6 
7 8 9

답변3

이것이 최선의 솔루션인지 확신할 수 없고 거대한 테이블에서 빠르게 작동할지 확신할 수 없지만 다음과 같이 작동해야 합니다.

echo -e  "2 1 3\n5 4 6\n8 7 9"  | \
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}}' \ 
     | sort -n  | \
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}}'

작동 방식: 테이블을 전치한 다음 테이블을 정렬하고 다시 전치합니다.

btw는 echo -e "2 1 3\n5 4 6\n8 7 9"다음과 같은 결과를 가져올 것입니다.

2 1 3
5 4 6
8 7 9

스크립트 작업 후에는 다음과 같은 결과가 발생합니다.

1 2 3
4 5 6
7 8 9

추신. awk에서 배열을 정렬하는 것이 가능하다고 생각합니다. 불행히도 그렇게 할 시간이 충분하지 않습니다.

답변4

파일이 xy.dat이고 공백으로 구분되어 있다고 가정합니다.

cat xy.dat | while read line ; do  
   echo $line | tr ' ' '\n' | sort -nr | tr '\n' ' '
   echo
done

내 테스트 데이터가 숫자 오름차순이었기 때문에 내림차순으로 만들기 위해 정렬 -nr을 사용하여 효과를 확인했습니다.

이제 구성 가능하게 하려면 오름차순(없음) 및 내림차순 -r(역방향)뿐만 아니라 -n(숫자) 및 기타 여러 가지를 허용하는 정렬 플래그를 매개변수로 전달하면 됩니다(참조: sort --help). 구성할 수 있는 또 다른 사항은 구분 기호입니다. 공백/탭/세미콜론/쉼표? 정규식 그룹이 "[ \t]"공백 또는 탭을 의미하는 것 같나요? 그러면 출력에 무엇을 사용해야 할까요? 그리고 파일 이름을 하드코딩하고 싶지는 않지만 프로그램을 필터로 사용하십시오. 빠른 접근 방식은 다음과 같습니다.

#!/bin/bash
flags=$1
delim=$2 
while read line ; do  
    echo $line | tr "$delim" '\n' | sort $flags | tr '\n' "$delim"
    echo
done

기도:

cat num.dat | bash colsort.sh "-nr" ' ' 
4 3 2 1 
8 7 6 5 
11 10 9 

cat num.dat | bash colsort.sh "-r" ' ' 
4 3 2 1 
8 7 6 5 
9 11 10 

cat num.dat | bash colsort.sh "--" ' ' 
1 2 3 4 
5 6 7 8 
10 11 9 

--(알파벳순: 10 11 9), 역방향(9 10 11) 또는 숫자(11 10 9)를 사용하여 기본적으로 정렬되는 방식을 확인하세요.

주로 공백, 탭 등을 마스크하는 방법을 문서화하면 도움이 될 것입니다.

관련 정보