正規表現に基づいてテキストファイルを分割する


16

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

しかし、この正規表現に従って実際にテキストファイルを64個の新しいファイルに分割するにはどうすればよいですか?のタスクのようですperl。しかし、おそらく、私がまったく見逃しているもっと明白な方法があるかもしれません。

回答:


23

これはcsplit、正規表現が1行でなければならないことを除いてです。それはまたsed難しくなります。私はPerlまたはPythonを使います。

あなたが見ることができます

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

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


ありがとう、@ geekosaur。完全に機能しましたが、{63}に変更する必要がありました。
ixtmixilix

1
だから、'\.'うまくいきませんか?
バヌアン

4

最良の方法はawkと思いますgawk

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は3つのフィールドに分割されます:1 Ch'ienおよびThe Creative。後でこれらのフィールドを参照できます$n$0行全体です。

次に、パターンと行を一致させるようにawkに指示 ^[0-9]{1,3}[.]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

3

GNU coreutilsでは、geekosaurが示すようにcsplit、ファイルを正規表現で区切られた部分に分割するために使用できます。

これは、ファイルを断片に分割する移植可能なawkスクリプトです。によって動作します

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

これは原理的には機能ますが、実際のWebページデータのセクションヘッダーは正規表現で表されているものではありません(ギークサウルスの回答と同様)。先頭のnunber. 後には、スラッシュを含むテキストが続きます/。上記のtwo newlines ixtmixilixは数値識別子の前にある2行の空白行であり、ヘッダーをより具体的に特定するものと確信していますが、Webページのデータ/^[0-9]+\. はセクションヘッダーでのみ一致するため、それらに対応する必要はありません(この特定の場合)。ありがとう。特にgetlinePS へのイントロのために。もしそうなら?
Peter.O

@fred geekosaurと私は、ウェブサイトのデータではなく、質問の説明を参考にしました。レイアウトは、テキストへの変換に使用されるHTMLレンダリングエンジンに依存します。これがWebページからレンダリングされる部分は、実際には質問とは無関係です。||| while入力に含まれる場合1.\n2.\n\n\n改行がある場合):2.ヘッダー行で認識される必要があります。ここでは発生しませんが、より一般的にするためにコードでサポートしています(そして質問の仕様をより厳密に一致させます)。
ジル 'SO-悪であるのをやめる'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.