1行で区切られた項目を数字でソートする方法は?

1行で区切られた項目を数字でソートする方法は?

任意の文字で区切られた数値行があります。区切り文字を保持しながら各行の項目を数値で並べ替えるために使用できる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'.' -

変える指す .区切り記号で。重複を排除するために上記のコマンドに
追加されました。-usort

メモ:
任意の種類の数値(整数、浮動小数点、エンジニアリング、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

に基づいて

関連情報