나는 많은 수의 열을 재정렬하기 위한 파이프라인 가능한 한 줄의 코드를 찾고 있습니다(예를 들어 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}}'
작동 방식: 테이블을 전치한 다음, 테이블을 정렬하고 다시 전치합니다.
그건 그렇고 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
PS 저는 awk에서 배열을 정렬하는 것이 가능하다고 생각했는데, 안타깝게도 그렇게 할 시간이 충분하지 않았습니다.
답변4
파일이 공백으로 구분된 xy.dat라고 가정합니다.
cat xy.dat | while read line ; do
echo $line | tr ' ' '\n' | sort -nr | tr '\n' ' '
echo
done
내 테스트 데이터가 수치적으로 오름차순이었기 때문에 정신적으로 sort -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) 등 기본적으로 정렬되는 방법을 확인하세요.
주로 공백, 탭 등을 마스크하는 방법을 문서화하면 도움이 될 것입니다.