임의의 문자로 구분된 숫자 행이 있습니다. 구분 기호를 유지하면서 각 줄의 항목을 숫자로 정렬하는 데 사용할 수 있는 UNIX 도구는 무엇입니까?
예는 다음과 같습니다:
- 숫자 목록 입력:
10 50 23 42
;정렬:10 23 42 50
- IP 주소;입력:
10.1.200.42
;정렬:1.10.42.200
- CSV;입력:
1,100,330,42
;정렬:1,42,100,330
- 수직 막대로 구분됨: 입력:
400|500|404
;400|404|500
구분 기호는 임의적이므로 원하는 단일 문자 구분 기호를 사용하여 자유롭게 답변을 제공(또는 확장)하세요.
답변1
그리고 gawk
(암소 비슷한 일종의 영양 awk
) 을 위한asort()
기능:
gawk -v SEP='*' '{ i=0; split($0, arr, SEP); len=asort(arr);
while ( ++i<=len ){ printf("%s%s", i>1?SEP:"", arr[i]) };
print ""
}' infile
*
필드 구분 기호를 SEP='*'
귀하의 것으로 바꾸십시오.구분 기호.
한 줄인 경우 다음 명령을 사용할 수도 있습니다(텍스트 처리에 쉘 루프를 사용하지 않는 것이 더 좋기 때문입니다.)
tr '.' '\n' <<<"$aline" | sort -n | paste -sd'.' -
바꾸다가리키다 .
구분 기호로. 중복을 제거하기 위해 위 명령 에
추가되었습니다 .-u
sort
노트:
모든 종류의 숫자(정수, 부동 소수점, 공학용, 16진수 등)를 처리하기 위해 대신 -g, --general-numeric-sort
옵션을 사용할 수 있습니다 .sort
-n, --numeric-sort
$ aline='2e-18,6.01e-17,1.4,-4,0xB000,0xB001,23,-3.e+11'
$ tr ',' '\n' <<<"$aline" |sort -g | paste -sd',' -
-3.e+11,-4,2e-18,6.01e-17,1.4,23,0xB000,0xB001
변경이 필요 하지 않으며 awk
계속 처리됩니다.
답변2
사용할 수 있는 perl
확실한 버전이 있습니다 . 데이터를 분할하고, 정렬하고, 다시 결합합니다.
구분 기호는 두 번 나열되어야 합니다( 에 한 번 split
, 에 한 번 join
).
예를 들어,
perl -lpi -e '$_=join(",",sort {$a <=> $b} split(/,/))'
그래서
echo 1,100,330,42 | perl -lpi -e '$_=join(",",sort {$a <=> $b} split(/,/))'
1,42,100,330
split
정규식 이므로 이 문자를 따옴표로 묶어야 할 수도 있습니다.
echo 10.1.200.42 | perl -lpi -e '$_=join(".",sort {$a <=> $b} split(/\./))'
1.10.42.200
-a
및 옵션을 사용하면 -F
분할을 제거할 수 있습니다. 이전과 같이 루프를 사용 -p
하고 결과를 로 설정하면 $_
자동으로 인쇄됩니다.
perl -F'/\./' -aple '$_=join(".", sort {$a <=> $b} @F)'
답변3
Python 및 유사한 아이디어 사용스티븐 해리스의 답변:
python3 -c 'import sys; c = sys.argv[1]; sys.stdout.writelines(map(lambda x: c.join(sorted(x.strip().split(c), key=int)) + "\n", sys.stdin))' <delmiter>
그래서 이렇게 :
$ cat foo
10.129.3.4
1.1.1.1
4.3.2.1
$ python3 -c 'import sys; c = sys.argv[1]; sys.stdout.writelines(map(lambda x: c.join(sorted(x.strip().split(c), key=int)) + "\n", sys.stdin))' . < foo
3.4.10.129
1.1.1.1
1.2.3.4
불행하게도 I/O를 수동으로 수행해야 하는 것은 Perl 버전보다 훨씬 덜 우아합니다.
답변4
쿵쿵 스크립트:
#!/usr/bin/env bash
join_by(){ local IFS="$1"; shift; echo "$*"; }
IFS="$1" read -r -a tokens_array <<< "$2"
IFS=$'\n' sorted=($(sort -n <<<"${tokens_array[*]}"))
join_by "$1" "${sorted[@]}"
예:
$ ./sort_delimited_string.sh "." "192.168.0.1"
0.1.168.192
기반으로