[英]Splitting a File with multiple header line
我正在尝试使用以下代码拆分具有多个 header 行的大文件。 虽然在工作; 但是在拆分文件中的 header 之后引入了一个空行。 如何摆脱空行?
/^@/ {
hdr = hdr $0 ORS
next
}
split($NF, a, ":")
!seen[a[3]]++{
out = a[3] ".txt"
print hdr > out
}
{out = a[3] ".txt"
print >> out
close(f)}
输入文件
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
S1 yes yes no yes 3y Mother Z:AgeGroup:A1
S17 yes no no yes 27y Mother Z:AgeGroup:A2
B13 no no no yes 1y Mother Z:AgeGroup:A3
B5 yes yes yes yes 76y Mother Z:AgeGroup:A1
D1 yes yes no no 18y Mother Z:AgeGroup:A1
预期 output
A1.txt
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
S1 yes yes no yes 3y Mother Z:AgeGroup:A1
B5 yes yes yes yes 76y Mother Z:AgeGroup:A1
D1 yes yes no no 18y Mother Z:AgeGroup:A1
A2.txt
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
S17 yes no no yes 27y Mother Z:AgeGroup:A2
A3.txt
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
B13 no no no yes 1y Mother Z:AgeGroup:A3
但是我的脚本得到的是
A1.txt
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
S1 yes yes no yes 3y Mother Z:AgeGroup:A1
B5 yes yes yes yes 76y Mother Z:AgeGroup:A1
D1 yes yes no no 18y Mother Z:AgeGroup:A1
A2.txt
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
S17 yes no no yes 27y Mother Z:AgeGroup:A2
A3.txt
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
B13 no no no yes 1y Mother Z:AgeGroup:A3
由于您每次都在hdr
字段中附加ORS
,然后在使用print hdr > out
它最终会 append 另一个换行符。
您应该像这样使用printf
:
printf "%s", hdr > out
$ cat tst.awk
BEGIN { FS=":" }
/^@/ {
hdr = hdr $0 ORS
next
}
!($NF in out) {
out[$NF] = $NF ".txt"
printf "%s", hdr > out[$NF]
}
{
print >> out[$NF]
close(out[$NF])
}
$ awk -f tst.awk file
$ head *.txt
==> A1.txt <==
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
S1 yes yes no yes 3y Mother Z:AgeGroup:A1
B5 yes yes yes yes 76y Mother Z:AgeGroup:A1
D1 yes yes no no 18y Mother Z:AgeGroup:A1
==> A2.txt <==
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
S17 yes no no yes 27y Mother Z:AgeGroup:A2
==> A3.txt <==
@Loc: Cali
@Yr: 2017
@ST: blood
@header information
B13 no no no yes 1y Mother Z:AgeGroup:A3
代码中最大的问题是split($NF, a, ":")
行,它会触发 awk 打印当前行,因此当您运行它时,您一定已经看到所有输入都回显到屏幕上。 这在你的问题中值得一提。 如果你真的想以这种方式使用split()
那么你应该把它放在一个动作块中,而不是作为一个条件,即{ split($NF, a, ":") }
。
除此之外:
close(f)
但没有名为f
的变量,因此它什么都不做,让您面临“打开的文件过多”错误或执行速度降低的风险,并且print
而不是printf
再次添加它到 output 之后,打印了每个额外的 hdr 块 hdr。对于您展示的样品,请尝试遵循awk
代码。 使用您显示的示例编写和测试,应该在任何awk
版本中工作(尽管我在 GNU awk
中测试过)。
awk '
BEGIN { FS=OFS=":" }
FNR==NR{
header=(header?header ORS:"") $0
next
}
prev!=$NF{
close(outputFile)
outputFile=$3".txt"
print header ORS > (outputFile)
}
{
print > (outputFile)
prev=$NF
}
' <(awk '/^@/{print;next} {exit}' Input_file) <(grep -v '^@' Input_file | sort -t: -k1.1)
代码说明:在此处添加上述代码的详细说明。
awk '/^@/{print;next} {exit}' Input_file
(检查最后一行的第一个参数到主awk
)。 我只打印从@
开始并尽快退出的行,任何非@
行都按照显示的示例出现。 此 output 作为第一组输入发送到主awk
。grep -v '^@' Input_file | sort -t: -k1.1
grep -v '^@' Input_file | sort -t: -k1.1
,通过这个,我只是将不是从@
开始的每一行作为主awk
的第二输入。awk
代码中:我正在使用条件FNR==NR
当第一个输入(上面在我的第一个点中提到的)被读取时,这将是 TRUE。 在这段代码中,我正在创建名为header
的awk
变量,它的所有行都用新行分隔,以供以后使用。next
非常重要,因为它将跳过从这里开始的所有进一步的语句,直到FNR==NR
为 TRUE。prev
是否不等于当前行的第三个字段,然后只需在后端closing
output 文件(我们需要在其中获取输出)基本上避免too many files opened
错误. 将当前第三个字段的值设置为 output 文件名。outputFile
变量(其中包含 output 文件名)并将当前 $3 的值分配给 outputFile 以在下一行检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.