
任意の文字で区切られた数値行があります。区切り文字を保持しながら各行の項目を数値で並べ替えるために使用できる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='*'
あなたのものに置き換えます。区切り記号。
1行の場合は、次のコマンドを使用することもできます(テキスト処理にシェルループを使用しない方が良いためです。)
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
確実なバージョンがあります。データを分割、並べ替え、再結合します。
区切り文字は2回リストする必要があります(1回split
、1回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
に基づいて