web-dev-qa-db-ja.com

正規表現に基づくテキストファイルの分割

Yi Jingの64ヘキサグラムによると、64の等しくない部分に分割したいテキストファイルがあります。各ヘキサグラムのパッセージは、いくつかの数字、ピリオド、2つの改行で始まるため、正規表現は非常に簡単に記述できます。

しかし、この正規表現に従って実際にテキストファイルを64個の新しいファイルに分割するにはどうすればよいですか? Perlの方がタスクのようです。しかし、多分私が完全に見落としているもっと明白な方法があるでしょう。

16
ixtmixilix

これはcsplitになりますが、正規表現は1行である必要があります。これもsedを難しくします。 PerlまたはPythonを使用します。

あなたは

csplit foo.txt '/^[0-9][0-9]*\.$/' '{64}'

あなたの目的には十分です。 (csplitはPOSIX BREを必要とするため、特に\dまたは+は使用できません。)

23
geekosaur

awkgawkが最善の方法だと思います。

awk

_awk -F "([.] )|( / )" '/^[0-9]{1,3}[.]/{x="F"$1"("$2").txt";}{print >x;}' I_Ching_Wilhelm_Translation.txt
_

_-F_は、各行のフィールドセパレータを指定します。これは正規表現です。ここでは、_". "_および_" / "_の複数のセパレータを使用しています。したがって、_1. Ch'ien / The Creative_のような行は、_1_ _Ch'ien_および_The Creative_の3つのフィールドに分割されます。後でこれらのフィールドを_$n_で参照できます。 _$0_は行全体です。

次に、行をパターン_^[0-9]{1,3}[.]_と一致させるようにawkに指示します。一致がある場合は、xに値を割り当てます。値xは、print操作のファイル名として使用されます。この例では"F"$1"("$2").txt"を使用しているため、_1. Ch'ien / The Creative_という行でファイル名を指定しますF1(Ch'ien).txt

ガウク

Gawkでは、キャプチャされたグループにもアクセスできます。したがって、次のようにコマンドを簡略化できます。

_gawk 'match($0, /^([0-9]{1,3})[.] (.*) \/ (.*)$/, ary){x="F"ary[1]"("ary[2]")";}{print >x;}' I_Ching_Wilhelm_Translation.txt
_

ここでは、matchを使用してグループをキャプチャし、変数リストaryに入れます。 _$0_は行全体です。 _ary[0]_はすべて一致します。 _ary[1...n]_は各グループです。

Perl

Perlでもそれを行うことができます:

_Perl -ne 'if(/^([0-9]{1,3})[.] (.*) \/ (.*)$/) {close F; open F, ">", sprintf("F$1($2).txt");} print F' I_Ching_Wilhelm_Translation.txt
_

結果:

_> ls F*
F10(Lü).txt         F22(Pi).txt       F34(Ta Chuang).txt  F46(Shêng).txt     F58(Tui).txt
F11(T'ai).txt       F23(Po).txt       F35(Chin).txt       F47(K'un).txt      F59(Huan).txt
F12(P'i).txt        F24(Fu).txt       F36(Ming I).txt     F48(Ching).txt     F5(Hsü).txt
F13(T'ung Jên).txt  F25(Wu Wang).txt  F37(Chia Jên).txt   F49(Ko).txt        F60(Chieh).txt
F14(Ta Yu).txt      F26(Ta Ch'u).txt  F38(K'uei).txt      F4(Mêng).txt       F61(Chung Fu).txt
F15(Ch'ien).txt     F27(I).txt        F39(Chien).txt      F50(Ting).txt      F62(Hsiao Kuo).txt
F16(Yü).txt         F28(Ta Kuo).txt   F3(Chun).txt        F51(Chên).txt      F63(Chi Chi).txt
F17(Sui).txt        F29(K'an).txt     F40(Hsieh).txt      F52(Kên).txt       F64(Wei Chi).txt
F18(Ku).txt         F2(K'un).txt      F41(Sun).txt        F53(Chien).txt     F6(Sung).txt
F19(Lin).txt        F30(Li).txt       F42(I).txt          F54(Kuei Mei).txt  F7(Shih).txt
F1(Ch'ien).txt      F31(Hsien).txt    F43(Kuai).txt       F55(Fêng).txt      F8(Pi).txt
F20(Kuan).txt       F32(Hêng).txt     F44(Kou).txt        F56(Lü).txt        F9(Hsiao Ch'u).txt
F21(Shih Ho).txt    F33(TUN).txt      F45(Ts'ui).txt      F57(Sun).txt
_

サンプルファイルの取得方法:

_curl http://www2.unipr.it/~deyoung/I_Ching_Wilhelm_Translation.html|html2text -o I_Ching_Wilhelm_Translation.plain
sed 's|^[[:blank:]]*||g' I_Ching_Wilhelm_Translation.plain > I_Ching_Wilhelm_Translation.txt
_
4
Wang

GNU coreutilsを使用すると、csplitを使用してファイルを正規表現で区切られた部分に分割できます geekosaurで示されているように

ファイルを分割するポータブルawkスクリプトを次に示します。それは

  • getlineを呼び出して、複数行(2行)の区切り記号を処理します。
  • セクションヘッダーが検出されたときに、変数outfileを出力先のファイルの名前に設定します。
BEGIN {outfile="header.txt"}
{
    while (/^[0-9]+\.$/) {
        prev = $0; getline;
        if ($0 == "") outfile = prev "txt";
        print prev >outfile
    }
    print >outfile
}