Бесконечная рекурсия в gawk-скрипте

Пожалуйста, извините меня заранее за публикацию такой большой части моей проблемы, но я просто не могу указать на ту часть, которая не работает...

У меня есть входные файлы, подобные этому (abas-FO, если вам интересно знать):

.fo U|xiininputfile = whatever
.type text U|xigibsgarnich
.assign U|xigibsgarnich
..
..Comment
.copy U|xigibswohl = Spaß
.ein "ow1/UWEDEFTEST.FOP"
.in "ow1/UWEINPUT2"
.continue BOTTOM
.read "SOemthing" U|xttmp
!BOTTOM
..
..

Теперь я хочу рекурсивно следовать каждому оператору .in[put]/.ein[gabe], анализировать упомянутый файл и, если я еще не знаю его, добавить его в массив. Мой код выглядит так:

#!/bin/awk -f

function getFopMap(inputregex, infile, mandantdir, infiles){
    while(getline f < infile){
        #printf "*"
        #don't match if there is a '
        if(f ~ inputregex "[^']"){
            #remove .input-part
            sub(inputregex, "", f)
            #trim right
            sub(/[[:blank:]]+$/, "", f)
            #remove leading and trailing "
            gsub(/(^\"|\"$)/,"" ,f)

            if(!(f in infiles)){
                infiles[f] = "found"
            }
        }
    }
    close(infile)

    for (i in infiles){
        if(infiles[i] == "found"){
            infiles[i] = "parsed"
            cmd = "test -f \"" i "\""
            if(system(cmd) == 0){
                close(cmd)
                getFopMap(inputregex, f, mandantdir, infiles)
            }
        }
    }
}

BEGIN{
    #Matches something like [.input myfile] or [.ein    "ow1/myfile"]
    inputregex = "^\\.(in|ein)[^[:blank:]]*[[:blank:]]+"

    #Get absolute path of infile
    cmd = "python -c 'import os;print os.path.abspath(\"" ARGV[1] "\")'"
    cmd | getline rootfile
    close(cmd)

    infiles[rootfile] = "parsed"
    getFopMap(inputregex, rootfile, mandantdir, infiles)

    #output result
    for(infile in infiles) print infile
    exit
}

Я вызываю скрипт (в том же каталоге, к которому относятся пути) следующим образом:

./скрипт вл1/UWEDEFTEST.FOP

Я не получаю выход. Просто зависает. Если я удалю комментарий перед командой printf "*", я увижу звезды без конца.

Я ценю каждую помощь и подсказки, как сделать это лучше.

Мой awk: gawk Версия 3.1.7


person Nils-o-mat    schedule 25.09.2014    source источник
comment
Вы делаете все в блоке BEGIN.   -  person fedorqui 'SO stop harming'    schedule 25.09.2014
comment
Это очень старая версия gawk, вам действительно следует обновиться до текущей версии, так как вам не хватает многих очень полезных функций.   -  person Ed Morton    schedule 25.09.2014
comment
@fedorqui Я знаю. Позже в программе я должен рекурсивно читать найденные файлы, поэтому я не вижу причин использовать функцию {}, которая обрабатывает только один файл. Но, возможно, я упускаю что-то важное...   -  person Nils-o-mat    schedule 25.09.2014
comment
@ Эд Мортон, я знаю. Но это должно работать на очень старых клиентских серверах, и как ученик я не в состоянии запрашивать обновления...   -  person Nils-o-mat    schedule 25.09.2014


Ответы (1)


idk, это ваша единственная проблема, но вы неправильно вызываете getline и, следовательно, в некоторых сценариях попадете в бесконечный цикл. Убедитесь, что вы полностью понимаете все предостережения на странице http://awk.info/?tip/getline. и вы можете использовать пример рекурсии в качестве отправной точки для своего кода.

Первоначально наиболее важным элементом для вашего кода является то, что при сбое getline он может возвращать отрицательное значение, поэтому while(getline f < infile) создаст бесконечный цикл, поскольку сбойный getline всегда будет возвращать ненулевое значение и поэтому будет продолжать вызываться и продолжать давать сбой. Вместо этого вам нужно использовать while ( (getline f < infile) > 0).

person Ed Morton    schedule 25.09.2014
comment
Я добавил первый шаг для вас к моему ответу. - person Ed Morton; 25.09.2014
comment
Я только что наткнулся на это ... Извините, что беспокою вас. Хорошего дня. - person Nils-o-mat; 25.09.2014