3264880줄이 넘는 대용량 파일이 있습니다. 이 파일을 "BEGIN JOB"과 "END JOB"이라는 두 문자열을 기준으로 분할하여 여러 파일에 쓰고 싶습니다. 파일 이름은 두 문자열 과 Identifier
행 사이에 있는 일부 문자열을 기준으로 해야 합니다.BEGIN JOB
END JOB
견본
BEGIN JOB
Identifier "ADHOC_Extract"
DateModified "2018-10-02"
TimeModified "15.09.52"
BEGIN DSRECORD
Identifier "ROOT"
OLEType "CJobDefn"
Readonly "0"
Name "ADHOC_Extract"
END JOB
BEGIN JOB
Identifier "HOC_Extract"
DateModified "2018-11-02"
TimeModified "12.09.52"
BEGIN DSRECORD
Identifier "ROOT"
OLEType "CJobDefn"
Readonly "0"
Name "HOC_Extract"
END JOB
내 샘플에는 2개만 있으므로 출력은 2개의 파일이 될 것으로 예상됩니다. 하지만 이와 같은 반복 패턴이 1000개가 넘습니다.
ADHOC_Extract.txt
BEGIN JOB
Identifier "ADHOC_Extract"
DateModified "2018-10-02"
TimeModified "15.09.52"
BEGIN DSRECORD
Identifier "ROOT"
OLEType "CJobDefn"
Readonly "0"
Name "ADHOC_Extract"
END JOB
HOC_Extract.txt
BEGIN JOB
Identifier "HOC_Extract"
DateModified "2018-11-02"
TimeModified "12.09.52"
BEGIN DSRECORD
Identifier "ROOT"
OLEType "CJobDefn"
Readonly "0"
Name "HOC_Extract"
END JOB
이를 위해 쉘 스크립트를 작성할 수도 있습니다.
답변1
GNU awk 사용
gawk -v RS="" '
match($0, /Identifier "([^"]+)/, m) {
print > (m[1]".txt")
close(m[1]".txt")
}
' sample.txt
Perl을 사용하면 CPAN의 편리한 Path::Tiny 모듈을 사용할 수 있습니다.
perl -MPath::Tiny -00 -ne '/Identifier "(.+?)"/ and path("$1.txt")->spew($_)' sample.txt
답변2
이 명령은 데이터의 단락 형식이 동일한 경우(예: 단락당 10줄) split
잘 작동합니다 .분열된 사람들).
#!/bin/bash
#remove blank lines from the original dataset.
awk NF original_data.txt > Free_spaces_data.txt
# split the dataset into files (paragraph per file), each paragraph is 10 lines.
split -l 10 Free_spaces_data.txt new
#rename the files based on the internal name within each paragraph
for f in ./new*?; do
name=$(cat $f | awk -F'"' '/Name/{print $2}')
mv "${f}" "${name}.txt";
done
답변3
파일 이름을 추출하려면 첫 번째 "식별자" 줄을 사용합니다.
awk '
!/^ *$/ {BUF = BUF RS $0
}
! FN &&
/Identifier/ {FN = $NF ".txt"
gsub (/"/, "", FN)
}
/END JOB/ {print BUF > FN
BUF = FN = ""
}
' file
빈 줄을 건너뛰고, 실제 줄을 버퍼에 추가하고, 첫 번째(FN null) "식별자"가 발생할 때 파일 이름을 생성하고, 모든 것을 제거하고 "
, 버퍼를 END JOB
, 재설정 BUF
및 FN
비어 있는 상태로 인쇄합니다.