I Ching의 64개 헥사그램을 기반으로 64개의 동일하지 않은 부분으로 나누고 싶은 텍스트 파일이 있습니다. 각 육각형 문단은 몇 개의 숫자, 마침표, 두 개의 줄 바꿈으로 시작하므로 정규식을 작성하기 쉽습니다.
하지만 이 정규식을 기반으로 실제로 텍스트 파일을 64개의 새 파일로 분할하려면 어떻게 해야 할까요? 이것은 작업처럼 보입니다 perl
. 하지만 어쩌면 내가 완전히 놓치고 있는 더 분명한 방법이 있을 수도 있습니다.
답변1
예외는 csplit
정규식이 한 줄이어야 한다는 것입니다. 이것은 또한 상황을 sed
어렵게 만듭니다. 저는 Perl이나 Python을 선택하겠습니다.
당신은 볼 수 있습니다
csplit foo.txt '/^[0-9][0-9]*\.$/' '{64}'
귀하의 목적에 충분합니다. ( POSIX BRE가 필요하므로 등과 csplit
함께 사용할 수 없습니다 .)\d
+
답변2
내 생각에 가장 좋은 방법은 awk
과 입니다 gawk
.
앗
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"
so 라인을 사용하여 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 -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
csplit
GNU coreutils를 사용하면 파일을 정규식으로 구분된 조각으로 분할 할 수 있습니다 .괴짜 드래곤이 보여준 것처럼.
이것은 파일을 여러 부분으로 분할하기 위한 이식 가능한 awk 스크립트입니다. 작동 방식은 다음과 같습니다.
getline
여러 줄(2줄) 구분 기호를 처리하기 위해 호출됩니다.outfile
섹션 헤더가 나타나면 변수를 인쇄할 파일 이름으로 설정합니다.
BEGIN {outfile="header.txt"}
{
while (/^[0-9]+\.$/) {
prev = $0; getline;
if ($0 == "") outfile = prev "txt";
print prev >outfile
}
print >outfile
}
답변4
분할 이유가 다른 명령으로 각 청크를 처리하는 것이라면 GNU Parallel이 선택의 도구일 수 있습니다.
cat I_Ching_Wilhelm_Translation.txt |
parallel -N1 --pipe --regexp --recend '\n' --recstart '[0-9]{1,3}[.] [^\n]+ /' 'cat > {#}'
cat > {#}
이는 실행 명령으로 대체될 수 있습니다 .