GAWK不会在使用单个文件阻塞ENDFILE后终止

GAWK不会在使用单个文件阻塞ENDFILE后终止,awk,Awk,我在下面有一个gawk脚本,它读取一个文件,只打印出序列中没有X且在一定长度范围内的记录。我想修改文件,所以我让脚本写入一个临时文件,然后将其重命名为原始文件。gawk中的BEGINFILE和ENDFILE构造似乎很方便实现这一点。但是,由于某些原因,即使给定了单个文件参数,在执行ENDFILE中的代码后,gawk也不会退出。它似乎跳回另一行代码,然后挂起。有人知道是什么导致了这一切吗?奇怪的是,并不是每个FASTA文件都会出现这种情况,只有少数文件,我无法区分触发错误的文件和未触发错误的文件之

我在下面有一个gawk脚本,它读取一个文件,只打印出序列中没有X且在一定长度范围内的记录。我想修改文件,所以我让脚本写入一个临时文件,然后将其重命名为原始文件。gawk中的
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)
    }
}