web-dev-qa-db-ja.com

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

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

####################################
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

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

14
RYN

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つのレコードであると考えていました。

13
Peter Cordes

解決策は、まずブロック内の改行を選択した未使用の文字(以下の例では '|')に変更し、結果を並べ替え、選択したセパレーターを元の改行に戻すことです。

sed -e 'N; N; N; N; N; s/\n/|/g' file.txt \
| sort -k2,2 -t\| \
| sed 's/|/\n/g'
9
xhienne
_Perl -0ne 'print sort /(#+[^#]*)/g' file.txt
_
  • _Perl -0_ファイル全体を丸呑みします
  • /(....)/gレコードを照合して抽出する
  • _print sort ..._並べ替えて出力する
5
JJoao

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*を対応するセクションの各行に、低ASCII文字(入力では発生しそうにありません)を区切り文字として使用し、次にnumbersすべてのlinesを使用して追加します。同じセパレータ。その場合は、3番目と1番目のフィールドをsortingし、中央の列をcuttingし、最後のsedを使用して区切り文字を復元するだけです。上記の場合、KEY12KEY2の前にソートされるので、必要に応じてsortコマンドを調整してください。

2
don_crissti

POSIX Awk stdlibライブラリ を使用できます。

#!/usr/local/bin/awklib -f
$0 ~ "#" {x++}
{q[x] = q[x] ? q[x] RS $0 : $0}
END {
  arr_sort(q)
  for (x in q) print q[x]
}
2
Steven Penny