Metin dosyalarını normal ifadeye göre bölme


16

Yi Jing'in 64 heksagramına göre 64 eşit olmayan parçaya bölmek istediğim bir metin dosyası var. Her heksagram için pasaj bir basamak, bir nokta ve iki yeni satırla başladığından, normal ifadenin yazılması oldukça kolay olmalıdır.

Ancak bu normal ifadeye göre metin dosyasını nasıl 64 yeni dosyaya bölebilirim? Daha çok bir görev gibi görünüyor perl. Ama belki de tamamen eksik olmamın daha açık bir yolu var.

Yanıtlar:


23

Bu csplit, normal ifadenin tek bir satır olması dışında olurdu . Bu da sedzorlaştırır; Perl veya Python ile giderdim.

Görebiliyordu

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

amaçlarınız için yeterince iyidir. ( csplitPOSIX BRE gerektirir, bu nedenle \dveya +diğerleri arasında kullanılamaz .)


Teşekkürler @geekosaur. Mükemmel çalıştı, ancak {63} olarak değiştirmek zorunda kaldım.
ixtmixilix

1
Öyleyse '\.'de çalışmayacak mı?
Vanuan

4

Bence en iyi yol awkve gawk.

awk

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

-Fher satır için alan ayırıcı belirtir. Bu bir normal ifade, burada birden fazla ayırıcı kullanıyoruz: ". "ve " / ". Böylece benzeri bir çizgi 1. Ch'ien / The Creative3 alana bölünecektir: 1 Ch'ienve The Creative. Daha sonra bu alanlara başvurabiliriz $n. $0tüm çizgi.

Daha sonra awk'a satırları desenle eşleştirmesini söyleriz Eşleşme ^[0-9]{1,3}[.]varsa, değer atarız x. X değeri printişlem için dosya adı olarak kullanılacaktır . Bu örnekte "F"$1"("$2").txt", satırın 1. Ch'ien / The Creativebir dosya adı vermesiniF1(Ch'ien).txt

gawk

Gawk olarak, yakalanan gruba da erişebiliriz. Böylece şu komutu basitleştirebiliriz:

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

burada matchgrupların yakalanmasını kullanıyoruz ve değişken listesine koyuyoruz ary. $0tüm çizgi. ary[0]her şey eşleşir. ary[1...n]her gruptur.

perl

Bunu perl ile de yapabiliriz:

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

Sonuçlar:

> 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

örnek dosya nasıl alınır:

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 ile, csplitbir dosyayı geekosaur tarafından gösterildiği gibi regexp ile sınırlandırılmış parçalara bölmek için kullanabilirsiniz .

İşte bir dosyayı parçalara ayırmak için taşınabilir bir awk betiği. Tarafından çalışır

  • getlineçok satırlı (2 hatlı) ayırıcıyla başa çıkmak için çağrı ;
  • outfilebölüm üstbilgisiyle karşılaşıldığında yazdırılacak dosyanın adına bir değişken ayarlama .
BEGIN {outfile="header.txt"}
{
    while (/^[0-9]+\.$/) {
        prev = $0; getline;
        if ($0 == "") outfile = prev "txt";
        print prev >outfile
    }
    print >outfile
}

Bu prensipte çalışır , ancak gerçek web sayfası verilerinin bölüm başlığı normal ifadeyle temsil edildiği gibi değildir (aynı şekilde geekosaur'un cevabı ile). Lider nunber. bir çizgi içeren metin tarafından takip edilir /. Bahsedilen two newlines ixtmixilix , sayısal tanımlayıcıdan önce gelen ve daha özel olarak başlığı tanımlayan 2 boş satır olduğundan eminim , ancak web sayfasındaki veriler yalnızca /^[0-9]+\. bölüm başlıklarında eşleştiğinden , bunlara hitap etmeye gerek yoktur ( bu özel durumda). Teşekkürler; özellikle giriş için getline.. PS. süre ne olabilir?
Peter.O

@fred geekosaur ve ben, web sitesindeki verilerle değil, sorudaki açıklamaya gittik. Düzen, metne dönüştürmek için kullanılan HTML oluşturma motoruna bağlı olacaktır; bunun bir web sayfasından yapıldığı kısım aslında soru ile ilgisizdir. ||| whilegirdinin 1.\n2.\n\n( \nyeni satırlar nerede ) 2.olması durumunda : başlık satırında tanınması gerekir. Burada gerçekleşmeyecek, ancak kodumu daha genel hale getirmek için destekliyorum (ve sorudaki spesifikasyonu daha sıkı bir şekilde eşleştiriyorum).
Gilles 'SO- kötü olmayı kes'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.