3264880行を超える大容量ファイルがあります。このファイルを「BEGIN JOB」と「END JOB」という2つの文字列に基づいて分割して、複数のファイルに書きたいと思います。ファイル名は、2つの文字列と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
空の状態で印刷します。