行として複数行のテキストファイルを並べ替える


13

この形式のテキストファイルがあります。

####################################
KEY2
VAL21
VAL22
VAL23
VAL24
####################################
KEY1
VAL11
VAL12
VAL13
VAL14
####################################
KEY3
VAL31
VAL32
VAL33
VAL34

このファイルをKEY行ごとに並べ替えて、結果に次の4行を含めたいので、並べ替えられた結果は次のようになります。

####################################
KEY1
VAL11
VAL12
VAL13
VAL14
####################################
KEY2
VAL21
VAL22
VAL23
VAL24
####################################
KEY3
VAL31
VAL32
VAL33
VAL34

これを行う方法はありますか?


5
クロスポストしないでください
Zanna

@Zanna:UNIXとaskubuntuのセクションは互いに重複しているため、除外されていると思います!私は、UNIXのメタセクションでこれについて読んだと思う
RYN


@RYN問題は重複ではなく、実際には多くのSEサイトが重複していますが、回答者は他のサイトの回答を知らない可能性があります。
phk 16

回答:


12

msort(1)複数行のレコードを持つファイルをソートできるように設計されました。オプションのGUIと、通常の使いやすいコマンドラインバージョンがあります。(少なくとも、マニュアルを注意深く読み、例を探したい人...)

AFAICT、レコードに任意のパターンを使用することはできません。そのため、レコードが固定サイズ(文字や行ではなくバイト単位)である場合を除きます。 空白行で区切られた行のブロックであるレコードのオプションmsortがあり-bます。

-b毎回###...(最初の行を除く)の前に空白行を入れることで、入力を非常に簡単に機能する形式に変換できます。

デフォルトでは、stderrに統計を出力するため、少なくとも、入力全体が単一のレコードであると見なされたため、ソートされなかった時期を簡単に判別できます。


msortあなたのデータで動作します。 このsedコマンドは、1 #+行目を除くすべての行の先頭に改行を追加します-w。レコード全体を(辞書式に)ソートします 。レコードのどの部分をキーとして使用するかを選択するオプションがありますが、私はそれらを必要としませんでした。

また、余分な改行を削除しました。

$ sed '2,$ s/^#\+/\n&/' unsorted.records | msort -b -w 2>/dev/null 
####################################
KEY1
VAL11
VAL12
VAL13
VAL14

####################################
KEY2
VAL21
VAL22
VAL23
VAL24

####################################
KEY3
VAL31
VAL32
VAL33
VAL34

-r '#'レコードセパレータとして使用することはできませんでした。ファイル全体が1つのレコードであると考えました。


どうもありがとうございました; msortとても便利です。おかげで(-rこれは私が使用し、複数の#があるので、それがあるようだ-dし、それが働いた
RYN

涼しい!(+1)msort -qwr '#' ex 私のために動作します(出力の区切り記号を変更します)
-JJoao

8

解決策は、最初にブロック内のラインフィードを選択した未使用文字(下の例では「|」)に変更し、結果をソートして、選択したセパレータを元のラインフィードに戻すことです。

sed -e 'N; N; N; N; N; s/\n/|/g' file.txt \
| sort -k2,2 -t\| \
| sed 's/|/\n/g'

1
ありがとう。これは機能しますが、特にデータが汚れている場合は非常に汚れています!キーの後の行が100だった場合、;Nそこに100を入力する必要があり、テキスト自体で使用されていない文字を見つけるのは難しくなります。sortまたはawk、... に非常に適しています。複数行の並べ替えを行うことができます
RYN

4
perl -0ne 'print sort /(#+[^#]*)/g' file.txt
  • perl -0 ファイル全体を丸lurみ
  • /(....)/g レコードを照合して抽出する
  • print sort ... それらをソートして印刷する

2

KEYセクション内の任意の行数で機能する別の方法を次に示します。

# extract delimiter
delim=$(head -n1 <infile)
sed '/#/d;/KEY/h;G;s/\n/\x02/' infile | nl -ba -nrz -s $'\002' | sort -t $'\002' -k3 -k1,1 |
cut -d $'\002' -f2 | sed '/KEY/{x;s/.*/'"${delim}"'/;G}'

これは、区切り文字を変数に保存することで機能します(その後、入力から削除します)。次にKEY*、対応するセクションのn各行にセパレータとして低アスキー文字(入力で発生する可能性は低い)をl使用して追加し、同じセパレータを使用してすべてのinesを無効にします。それsortは、3番目と1番目のフィールドをcut呼び出し、中央の列を削除してから、finalを介して区切り文字を復元するだけsedです。上記でKEY12は、前にソートされるKEY2ためsort、必要に応じてコマンドを調整することに注意してください。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.