use strict; open my $text, '<', 'test.txt'; $/ = $, = '['; # input record separator, output field separator my %mapping; # existing endnote number --> number in ascendig order my $endnote_counter = 1; if (@ARGV && $ARGV[0] eq '--by_endnote_order') { while (<$text>) { # skip main text last if (/\@footnote:/); } while (<$text>) { # compute mapping in endnotes section if (/^(\d+)]/) { $mapping{$1} //= $endnote_counter++; } } } my @endnotes; seek($text, 0, 0); # nop if not --by_endnote_order while (<$text>) { # re-map endnote references in main text if (/^(\d+)(].*)$/ms) { $mapping{$1} //= $endnote_counter++; # nop if --by_endnote_order $_ = $mapping{$1}.$2; } print; last if (/\@footnote:/); } while (<$text>) { # re-order endnotes chomp; if (/^(\d+)(].*)$/ms) { $_ = $mapping{$1}.$2; } $endnotes[$mapping{$1}] .= ($endnotes[$mapping{$1}] ? '[' : q()) . $_; } print grep {$_} @endnotes; # omit endnote references without definition