Обратите внимание на комментарий в строке 2885 :
/* Here we just switch the register state and the stack. */
context_switch ()
не загружает новый указатель команд (счетчик программ) напрямую, он переключает стек - и стек содержит соответствующий адрес возврата. Когда функция возвращается, она возвращается к новой задаче.
При разветвлении виртуальный адрес возврата такой же, как в обоих процессах (родительском и дочернем); разница - это возвращаемое значение.
Используя 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
.
Вы можете изменить разделитель записей в POSIX awk
путем изменения RS
. POSIX не уточняет, может ли это быть регулярное выражение, говоря только
Неопределенное поведение от использования многосимвольных значений RS - это возможность возможных будущих расширений, основанных на расширенных регулярных выражениях, используемых для разделителей записей. Исторические реализации принимают первый символ строки и игнорируют остальные.
Однако, вы можете либо прочитать весь файл как строку (выбрав маловероятный RS
), либо, используя getline
, посмотреть на концы строк и срастить результат по мере необходимости.
С 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
В кулинарной книге 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"