GAWK不会在使用单个文件阻塞ENDFILE后终止
我在下面有一个gawk脚本,它读取一个文件,只打印出序列中没有X且在一定长度范围内的记录。我想修改文件,所以我让脚本写入一个临时文件,然后将其重命名为原始文件。gawk中的GAWK不会在使用单个文件阻塞ENDFILE后终止,awk,Awk,我在下面有一个gawk脚本,它读取一个文件,只打印出序列中没有X且在一定长度范围内的记录。我想修改文件,所以我让脚本写入一个临时文件,然后将其重命名为原始文件。gawk中的BEGINFILE和ENDFILE构造似乎很方便实现这一点。但是,由于某些原因,即使给定了单个文件参数,在执行ENDFILE中的代码后,gawk也不会退出。它似乎跳回另一行代码,然后挂起。有人知道是什么导致了这一切吗?奇怪的是,并不是每个FASTA文件都会出现这种情况,只有少数文件,我无法区分触发错误的文件和未触发错误的文件之
BEGINFILE
和ENDFILE
构造似乎很方便实现这一点。但是,由于某些原因,即使给定了单个文件参数,在执行ENDFILE
中的代码后,gawk也不会退出。它似乎跳回另一行代码,然后挂起。有人知道是什么导致了这一切吗?奇怪的是,并不是每个FASTA文件都会出现这种情况,只有少数文件,我无法区分触发错误的文件和未触发错误的文件之间有什么不同
#! /bin/gawk -f
function trim(s) {
gsub(/^[ \t]+|[ \t]+$/, "", s)
return s
}
function printFasta(header, seq, outfile, seq_line_max_chars) {
print ">" header > outfile
seq_line_max_chars = 80
start = 1
end = length(seq)
while (start <= end) {
print substr(seq, start, seq_line_max_chars) > outfile
start += seq_line_max_chars
}
}
BEGIN {
min_prot_len = 400
}
BEGINFILE {
tmp_out = FILENAME ".tmp"
}
/^>.+/ {
headerStartIdx = index($0, ">") + 1
header = trim(substr($0, headerStartIdx))
getline
sequence = ""
while ($0 !~ /(^>.+)|(^[[:space:]]*$)/) {
x_matched = match($0, "X")
if (x_matched != 0) {
next
}
gsub("*", "")
sequence = sequence $0
getline
}
if (length(sequence) >= min_prot_len) {
printFasta(header, sequence, tmp_out)
}
}
ENDFILE {
print "move called"
# system(("mv " tmp_out " " FILENAME))
}
运行此操作时,会打印名为的移动,然后挂起。我尝试单步执行调试器,看到它到达处理了输入文件中所有行的ENDFILE
块,但当我键入next
命令时,它会跳到第44行的getline
语句。在多次迭代next
和print$0
之后,程序似乎一直在读取输入文件的最后一行,直到时间结束。也许这是一个错误
我正在使用GAWK 5.1.0
编辑
最小输入文件。
当我只使用几个序列运行脚本时,它会工作,但当我使用整个文件时,它会挂起。我不知道如何在不提供整个文件的情况下制作一个最小的示例。在您提供样本输入以进行测试后,我们会确定,但是我的钱在循环中调用
getline
,到达文件的结尾,从而触发ENDFILE
条件为真,但是您仍然处于循环
看:
在循环中调用
getline
不是编写awk脚本的方式,代码中的语法在任何时候调用getline
时都是错误的-请参阅。我修改了脚本,删除了getline
,以防有人发现它有用
#! /bin/gawk -f
function printFasta(header, seq, seq_line_max_chars) {
print ">" header
seq_line_max_chars = 80
start = 1
end = length(seq)
while (start <= end) {
print substr(seq, start, seq_line_max_chars)
start += seq_line_max_chars
}
}
BEGIN {
FS = ">"
min_prot_len = 400
max_prot_len = 700
}
NF > 1 {
if (sequence &&
length(sequence) >= min_prot_len &&
length(sequence) <= max_prot_len) {
printFasta(header, sequence)
}
}
{
if (!header) {
next
} else {
x_in_seq = match($0, "X")
if (!x_in_seq) {
gsub("*", "")
sequence = sequence $0
} else {
header = ""
}
}
}
END {
if (header) {
printFasta(header, sequence)
}
}
#/垃圾箱/呆板-f
函数printFasta(标题、序号、序号行和最大字符){
打印“>”标题
seq_line_max_chars=80
开始=1
结束=长度(序号)
while(开始1{
如果(序列&&
长度(序列)>=最小保护长度&&
长度(顺序)请你的问题也提供一个我们可以测试的最小样本输入文件。当你问下一个问题时-不要发布链接或图像,在你的问题中发布文本。如果没有滚动条,任何样本输入或输出都不适合你的问题,那么这不是一个最小的示例。是的,我不想发布链接,但我找不到重复出现问题的最小序列数。我不知道为什么脚本可以工作几个序列,但会中断很多序列。看看你的循环,我想你会遇到每个输入文件的问题,这些文件的最后一行不是空的,因为对于以非空行结尾的文件,不是以
它只会在每次迭代中循环重新测试$0,每次失败时getline都会返回相同的最后一行,因为它已经到达了文件的末尾。我正在考虑这个问题,我怀疑getline
可能是问题所在。我是否应该将while循环中的正则表达式移到它自己的块中?我不知道您在想什么r脚本正在这样做,我不能建议它应该如何编写。你应该接受对你发布的问题的这个答案,并发布一个新的问题,如果你需要帮助,在第一步尝试摆脱getlines之后,找出如何以正确的方式做你正在尝试做的事情。
$ cat file
foo
bar
$ cat tst.awk
{
while (1) {
print "about to execute getline"
getline
print "just executed getline:", $0
if (++c == 5) {
exit
}
}
}
ENDFILE {
print "*** in ENDFILE ***"
}
$ awk -f tst.awk file
about to execute getline
just executed getline: bar
about to execute getline
*** in ENDFILE ***
just executed getline: bar
about to execute getline
just executed getline: bar
about to execute getline
just executed getline: bar
about to execute getline
just executed getline: bar
#! /bin/gawk -f
function printFasta(header, seq, seq_line_max_chars) {
print ">" header
seq_line_max_chars = 80
start = 1
end = length(seq)
while (start <= end) {
print substr(seq, start, seq_line_max_chars)
start += seq_line_max_chars
}
}
BEGIN {
FS = ">"
min_prot_len = 400
max_prot_len = 700
}
NF > 1 {
if (sequence &&
length(sequence) >= min_prot_len &&
length(sequence) <= max_prot_len) {
printFasta(header, sequence)
}
}
{
if (!header) {
next
} else {
x_in_seq = match($0, "X")
if (!x_in_seq) {
gsub("*", "")
sequence = sequence $0
} else {
header = ""
}
}
}
END {
if (header) {
printFasta(header, sequence)
}
}