정규식을 기반으로 텍스트 파일 분할


16

Yi Jing의 64 hexagrams에 따라 64 개의 동일하지 않은 부분으로 분할하려는 텍스트 파일이 있습니다. 각 hexagram에 대한 구절은 일부 숫자, 마침표 및 두 줄 바꿈으로 시작하므로 정규식을 작성하기가 매우 쉽습니다.

그러나이 정규식에 따라 실제로 텍스트 파일을 64 개의 새 파일로 어떻게 분할합니까? 에 대한 더 많은 작업처럼 보입니다 perl. 그러나 내가 완전히 놓친 더 분명한 방법이있을 수 있습니다.

답변:


23

이것은 csplit정규 표현식 이 한 줄이어야 한다는 것을 제외하고는 것입니다. 그것은 또한 sed어렵다. 나는 Perl이나 Python과 함께 갈 것이다.

당신은 볼 수 있습니다

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

당신의 목적에 충분합니다. ( csplit이 사용할 수 있도록 POSIX BRE는 필요 \d또는 +다른 사람의 사이에서.)


감사합니다, @geekosaur. {63}으로 변경해야했지만 완벽하게 작동했습니다.
ixtmixilix 2016 년

1
그래서 '\.'작동하지 않습니까?
Vanuan

4

가장 좋은 방법은 awkgawk입니다.

어 wk

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

-F각 줄에 대해 필드 구분 기호를 지정합니다. 그것은 정규식, 우리가 여러 seperators를 사용 ". "하고 " / ". 따라서 같은 줄 1. Ch'ien / The Creative은 3 개의 필드로 나뉩니다 : 1 Ch'ienThe 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 -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를 사용 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
}

이것은 원칙적으로 작동 하지만 실제 웹 페이지 데이터의 섹션 헤더는 정규 표현식으로 표시되지 않습니다 (예 : geekosaur의 답변). 선두는 nunber. 슬래시를 포함하는 텍스트 뒤에 /. 나는 ixtmixilix를 확신합니다two newlines 언급이 있습니다 이 빈 줄 숫자 ID를 앞에보다 구체적으로 헤더를 식별하는 것입니다,하지만 웹 페이지의 데이터 만 일치로 /^[0-9]+\. 섹션 헤더에, 그들에 대한 수용 할 필요가 (없다 이 특별한 경우). 감사; 특히 getlinePS 소개를 위해 .. PS. 만약에있을 수 있습니까?
Peter.O

@fred geekosaur와 나는 웹 사이트의 데이터가 아니라 질문에 대한 설명으로 갔다. 레이아웃은 텍스트로 변환하는 데 사용되는 HTML 렌더링 엔진에 따라 다릅니다. 이것이 웹 페이지에서 렌더링되는 부분은 실제로 질문과 관련이 없습니다. ||| while입력이 포함 된 경우가있다 1.\n2.\n\n(단, \n개행 문자 임) 다음은 2.헤더 라인으로 인식되어야한다. 여기서는 발생하지 않지만 코드에서 더 일반적으로 만들기 위해 지원합니다 (질문의 사양을보다 엄격하게 일치시킵니다).
Gilles 'SO- 악의를 멈춰라'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.