Почему мой AWK-Script ждет, пока я нажму клавишу? - PullRequest
3 голосов
/ 09 июля 2019

Я начал изучать AWK сегодня и написал сценарий, который рассчитывает степени двух.Когда я запускаю его, он ждет, пока я нажму клавишу ввода, и когда он завершит печать степеней двух, он не печатает слово «Конец», хотя оно определено в разделе «Конец».

Вот мойкод:

BEGIN{
    print "Power of two"
    x=0
}
{
while(res<=1000){
    res = 2^x
    print 2 "^" x "=" res
    x++
}
}
END{
    print "End"
}

Ответы [ 3 ]

2 голосов
/ 09 июля 2019

Вы сказали вашему сценарию ожидать ввода, предоставив код между BEGIN и END ({while ... }}) для обработки этого ввода.Этот раздел не начинается до тех пор, пока вы не введете ввод, нажав Enter, и затем не закончится, пока вы не завершите ввод, введя control-D, после чего будет выполнен ваш END-раздел.

Звучит такэто то, что вы намеревались написать вместо этого:

BEGIN{
    print "Power of two"
    x=0

    while(res<=1000){
        res = 2^x
        print 2 "^" x "=" res
        x++
    }

    print "End"
}

или если вы действительно хотите по какой-то причине иметь раздел END:

BEGIN{
    print "Power of two"
    x=0

    while(res<=1000){
        res = 2^x
        print 2 "^" x "=" res
        x++
    }

    exit
}
END{
    print "End"
}
2 голосов
/ 09 июля 2019

Причина, по которой ваша программа выполняет дальнейшие действия после нажатия клавиши, заключается в том, что она ожидает ввода.Обычно входные данные поступают из файлов или выходных данных другой команды при использовании канала.Однако время от времени awk может ожидать ввода от /dev/stdin.Это тот случай, когда вы вызываете вашу программу без каких-либо файлов в качестве аргумента (см. [1] раздел Расширенное описание: Общая структура программы ) или используете в качестве аргумента (см. [1] section Операнды ).

$ awk -f source.awk                 # input from /dev/stdin via keyboard 
$ awk -f source.awk [file] -        # input from /dev/stdin via [file and] keyboard
$ cmd | awk -f source.awk           # input from /dev/stdin via pipe
$ cmd | awk -f source.awk [file] -  # input from /dev/stdin via [file and] pipe

Имейте в виду, что приведенные выше случаи могут потребовать ввода от /dev/stdin.Необходимость ввода зависит от структуры программы awk.Таким образом, мы можем теперь задать себе следующий вопрос:

Когда awk требует ввода из файла, команды, клавиатуры или любой другой возможной формы ввода?

A awkПрограмма состоит из пар вида:

pattern { action }

, где pattern - это, как правило, логическое условие для определения, следует ли выполнять action.Posix awk распознает два специальных шаблона: BEGIN и END.У Gnu awk есть и другие специальные шаблоны, такие как BEGINFILE и ENDFILE, но для этого ответа мы можем классифицировать их как регулярные.Теперь мы можем сделать следующие утверждения (см. [1] подраздел Специальные шаблоны ):

  • Обычный шаблон всегда требует ввода.
  • Специальный шаблон BEGIN не требует ввода (кроме случаев, когда он содержит getline)
  • Специальный шаблон END всегда требует, чтобы ввод считывался перед его выполнением

Отсюда можно сказать:

Программе awk не требуется ввод если

  • , он состоит только из BEGIN паттернов, которые не вызывают getline.
  • или, BEGIN pattern вызывает exit подпрограмму до того, как может быть вызван любой getline.

в любом другом случае, awk потребует ввода!

Последнее утверждение происходит из правил, связанных с оператором exit.Оператор exit должен вызывать все действия END в том порядке, в котором они происходят в исходном коде программы, а затем завершать программу без чтения дополнительных данных .(См. [1] подраздел Действия )

Исходя из вышеизложенного, теперь мы можем ответить на вопрос ОП:

Почемумой AWK-Script ждет, пока я нажму клавишу?

Поскольку программа OP выглядит примерно так:

 BEGIN { something without exit }
 pattern { something else }
 END { something final }

, она потребует ввода.Кроме того, OP называет его как

$ awk -f file.awk

, что означает, что ввод поступает с /dev/stdin или, в данном случае, с клавиатуры.Поэтому awk будет ждать выполнения обычной пары action-pattern, пока не получит запись (здесь строка) с клавиатуры.Т.е. нажмите несколько клавиш, а затем Enter .Каждый раз, когда такая строка отправляется, awk будет обрабатывать все обычные шаблоны.Шаблон END будет выполняться только после завершения ввода.Вы можете сообщить awk, что ввод с клавиатуры завершен, отправив конец файла (EOF) через клавиатуру.Это делается нажатием Ctrl - D .

Чистая перезапись кода может быть найдена в ответе Ed Morton .Быстрый обходной путь в ответе Jotne .

[1]: стандарт Posix, раздел утилит, awk

1 голос
/ 09 июля 2019

У вас awk есть в средней части, которые требуют некоторого ввода (как пишет @Sundeep)

Попробуйте это

echo "50" | awk '
BEGIN{
    print "Power of two"
    x=0
}
{
while(res<=$1){
    res = 2^x
    print 2 "^" x "=" res
    x++
}
}
END{
    print "End"
}'
Power of two
2^0=1
2^1=2
2^2=4
2^3=8
2^4=16
2^5=32
2^6=64
End
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...