Может ли Awk читать экранированные новые строки? Т.е. читать прошедшие новые строки

Обратите внимание на комментарий в строке 2885 :

/* Here we just switch the register state and the stack. */

context_switch () не загружает новый указатель команд (счетчик программ) напрямую, он переключает стек - и стек содержит соответствующий адрес возврата. Когда функция возвращается, она возвращается к новой задаче.

При разветвлении виртуальный адрес возврата такой же, как в обоих процессах (родительском и дочернем); разница - это возвращаемое значение.

2
26.05.2016, 10:51
4 ответа

Используя GNU awk:

$ awk '{printf "%s%s%s","line=",$0,RT}' RS='[^\\\\]\n' text
line=entry1line1
line=entry2line1\
entry2line2\
entry2line3
line=entry3line1

Как видите, строки заканчиваются на \ присоединяются к следующей строке. Это связано с тем, что разделитель записей RS был переопределен так, чтобы он был любым без обратной косой черты, за которым следует новая строка. Другими словами, обратная косая черта-новая строка не является разделителем записей.

Небольшая хитрость заключается в том, что разделитель записей проглатывает последний символ записи. Однако этот символ сохраняется для нас во встроенной переменной RT . Небольшое изменение в программе исправляет значение $ 0 в начале кода, чтобы эта проблема исчезла:

$ awk '{$0=$0 substr(RT,1,1)} {print "line=",$0}' RS='[^\\\\]\n' text
line= entry1line1
line= entry2line1\
entry2line2\
entry2line3
line= entry3line1

RT содержит весь фактический наблюдаемый разделитель записей. В нашем случае это означает, что он имеет последний символ записи и следующий за ним символ новой строки. Следовательно, в приведенном выше коде substr используется для добавления первого символа RT в конец $ 0 .

1
27.01.2020, 22:04

Вы можете изменить разделитель записей в POSIX awk путем изменения RS. POSIX не уточняет, может ли это быть регулярное выражение, говоря только

Неопределенное поведение от использования многосимвольных значений RS - это возможность возможных будущих расширений, основанных на расширенных регулярных выражениях, используемых для разделителей записей. Исторические реализации принимают первый символ строки и игнорируют остальные.

Однако, вы можете либо прочитать весь файл как строку (выбрав маловероятный RS), либо, используя getline, посмотреть на концы строк и срастить результат по мере необходимости.

0
27.01.2020, 22:04

С posix awk вы можете использовать getline

awk '{while(/\\$/){getline tmp;$0=$0"\n"tmp}print "<LINE>"$0"<LINE>"}' file

Просто продолжайте добавлять следующую строку, пока последняя строка не заканчивается на \ .

<LINE>entry1line1<LINE>
<LINE>entry2line1\
entry2line2\
entry2line3<LINE>
<LINE>entry3line1<LINE>

То же в perl

perl -ne '$_.=<> while /\\$/;chomp;print "<LINE>$_<LINE>\n"' file
2
27.01.2020, 22:04

В кулинарной книге perl есть пример того, как это сделать с помощью perl.

Я адаптировал этот пример для работы с <> (стандартный ввод и / или другие имена файлов указываются как аргументы в командной строке), а не с именованным дескриптором файла, а также для сохранить новую строку после продолжения \ (что немного необычно - гораздо чаще требуется, чтобы продолженная строка рассматривалась как одна длинная строка, с продолжением, соединенным либо ничем, либо, возможно, пробелом).

perl -e '
$count=1;
while (defined($line = <>) ) {
    chomp($line);
    if ($line =~ s/\\$//) {
        $line .= "\n" . <>;
        redo unless eof();
    }
    # process full record in $line here
    printf "%04i:\"%s\"\n\n", $count++,$line;
}' willdavies.txt 

Вы можете делать все, что хотите, с помощью $ line после комментария, который гласит # обработать полную запись ... . Я решил просто печатать каждую строку как отдельный абзац со счетчиком строк, заполненным нулями. Я также добавил кавычки вокруг $ line , чтобы вы могли точно видеть, что находится в $ line (а что нет).

Вывод:

0001:"entry1line1"

0002:"entry2line1
entry2line2
entry2line3"

0003:"entry3line1"
0
27.01.2020, 22:04

Теги

Похожие вопросы