複数の文字長の区切り文字を使用してソートする方法は?

複数の文字長の区切り文字を使用してソートする方法は?

入力する:

$ cat a.txt 
1FOO2FOO3
4FOO5FOO5
2FOO1FOO9
$ 

出力:

$ cat a.txt | sort SOMEMAGIC
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5
$ 

質問:複数の文字長の区切り文字がある場合は、どのように並べ替えますか? (「FOO」)?

例では、a.txt2番目の列に基づいてソートします。

問題は、通常、数字はa.txt何でもよいということです。

答え1

sedたとえば、文字列を単一文字の区切り文字に置き換え、列で並べ替えてから区切り文字に置き換えるには、次のようにします。

sed -e s/FOO/X/g a.txt | sort -k 2,2 -t X | sed -e s/X/FOO/g 

これは、入力に文字が表示されないことを知っていると仮定します。制御文字は一般的な候補ですが、入力形式の知識に基づいて選択する必要があります。

答え2

この試み:

$ perl -ane '
    push @h,[$_,(split(/FOO/))[1]];
    END {
        print map  { $_->[0] }
              sort {$a->[1] <=> $b->[1]}
              @h;
    }
' file
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5

説明する

  • 各配列ref [line、key]を配列に保存します@h[$_,(split(/FOO/))[1]]

  • ファイルの読み取りが終わったら:

    • @hキーに基づいて配列の配列参照を並べ替えるsort {$a->[1] <=> $b->[1]}
    • 元の行を抽出して@h印刷します。map { $_->[0] }

答え3

フィールドが数値であると仮定すると、sortGNUバージョンの並べ替え役に立つかもしれません。のF尾がフィールド2に入り、フィールド2がvalueを含むものとして扱われるように区切り文字をに設定します。フィールド 2 にバージョンソートを指定すると、数値ではなく接頭辞が無視され、出力がフィールド 2 の末尾の数値部分に基づいてソートされます。OOFOOsortOO2, OO5 and OO1OO

sort -k2,2V -t 'F' a.txt
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5

または、awkインメモリソリューションのオーバーヘッドを許可できる場合は、GNUを使用してください。

awk -F'FOO' '{a[$2]=$0};END{asort(a, b, "@ind_num_asc");
for (i in b) print b[i]}' a.txt
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5

答え4

sort -k区分線よりは目に集中しすぎればいいと思います。キーの文字範囲を指定できます。

info sort

...入力ライン「foo bar」が与えられたら、sortそれを「foo」フィールドと「bar」フィールドに分割します。フィールド区切り文字は前または次のフィールドの一部とは見なされないため、「sort -t」「」を使用すると、同じ入力行に空のフィールド「foo」と「bar」という3つのフィールドがあります。ただし、行の終わりまで(または「-k 2」など)まで拡張されたフィールド(例:「-k 2,3」)、 範囲エンドポイント間のフィールド区切り文字を保持します。

Stephaneが述べたように、その逆も同様です。バイト範囲を持つフィールドの断片だけを並べ替えることも、複数のキーを持つ同じフィールドの複数の断片を並べ替えることもできます。したがって、あなたの場合は、異なる範囲で同じフィールドを複数回使用できます。願いより?

sort -k1.5n -k1.1n --debug <<\DATA
1FOO2FOO3
4FOO5FOO5
2FOO1FOO9
DATA
sort: using simple byte comparison
sort: leading blanks are significant in key 1; consider also specifying 'b'
sort: key 1 is numeric and spans multiple fields
sort: key 2 is numeric and spans multiple fields
2FOO1FOO9
    _
_
_________
1FOO2FOO3
    _
_
_________
4FOO5FOO5
    _
_
_________

sortこれは、主キーがフィールド1の5番目のバイトから始まり、フィールド1の終わりまで拡張され、次にフィールド1の最初のバイトからフィールド1の終わりまでソートされるように指示します。上記のように、この--debugオプションはソートしようとすると非常に便利です。sortしかし、ここにはデバッグはありません。

sort -k1.5n -k1.1n <<\DATA        
1FOO2FOO3
4FOO5FOO5
2FOO1FOO9
DATA

###OUTPUT###
2FOO1FOO9
1FOO2FOO3
4FOO5FOO5

それぞれに1文字だけを使用するには、sort範囲を狭くする必要があります。上記の例では、-k1.5nバイト5からフィールドの最後まで作業するのは、キー仕様が次のように機能するためです。

 -k[begin field].[first byte in key],[end field].[last byte in key]

したがって、この場合、結果は同じですが、次のように開くときと同じバイトで各フィールド範囲を閉じることができます。

sort -k1.5,1.5n -k1.1,1.1n

したがって、sort各キーは1バイトのみで構成されます。

関連情報