我有一个以下格式的文本文件:
Model 1
Atom….
Atom….
Atom….
ENDMDL
Model 2
Atom….
Atom….
Atom….
ENDMDL
Model n
Atom….
Atom….
Atom….
ENDMDL
我需要将这个文件拆分为每个模型对应的文件。新文件的名称根据型号编号。
答案1
这可以很容易地使用一个小awk脚本。
#!/usr/bin/awk -f
# Write sections of the input file to separate files
# Written by PM 2Ring 2016.06.14
BEGIN{outbase = "outfile"}
/^Model/{outname = outbase $2}
{print > outname}
outbase
是基本文件名。它会附加型号,因此对于您的示例文件,将创建输出文件、等outfile1
。outfile2
通过对脚本进行微小的更改,您可以outbase
使用 awk 的选项从命令行进行设置-v
。
这个脚本的核心是
/^Model/{outname = outbase $2}
它表示:如果当前行以“Model”开头,则将字段 #2 的内容附加到字符串中outbase
,并将结果分配给outname
.
默认情况下,awk 逐行处理文件,使用空格作为字段分隔符将每一行分割成字段。
{print > outname}
只是将当前行打印到名称存储在 中的文件中outname
。
这个脚本足够小,可以在命令行上编写整个内容:
awk 'BEGIN{outbase = "outfile"}; /^Model/{outname = outbase $2}; {print > outname}' infile.txt
实际上,您可以提供多个输入文件参数,只要您没有重复的型号,它们就会被正确处理。
答案2
我可能会使用csplit
.这适用于名为的文件file.txt
:
csplit -ksz file.txt '/^Model/' '{*}'
for xx in xx*
do
newname=$(awk '{print $2; exit}' "$xx")
test ! -f "$newname" && mv -f "$xx" "$newname"
done
根据 RE 拆分为多个部分csplit
。file.txt
文件名(默认情况下)命名为xx
单调递增的数字后缀。我们依次查看每个文件并将它们重命名为文件中找到的型号。
xx*
循环末尾匹配的任何文件都包含重复的型号(重命名是在先到先得基础)。
答案3
#!/bin/bash
while read -r line
do
case $line in
Model*)
f="${line//[[:space:]]/}"
touch "$f" # file name without white spces
;;
ENDMDL)
:
;;
*)
echo "$line" >> "$f"
;;
esac
done < "$1"
像这样的东西。您应该提供模型文件作为参数来运行它:./script_name models.txt
请注意,正如 @PM 2Ring 所提到的,这种方法很慢,特别是如果您有大文件。