Скажем, ваш ключ сортировки - это набор цифр в начале каждой строки, как в следующем примере.
5 Fine
2 Good
1 Every
4 Does
3 Boy
Чтобы отсортировать один или несколько файлов, названных в командной строке, вы можете использовать код ниже.
#! /usr/bin/env perl
use strict;
use warnings;
die "Usage: $0 file ..\n" unless @ARGV;
$^I = ".bak";
undef $/;
while (<>) {
print map $_->[0],
sort { $a->[1] <=> $b->[1] }
map { [ $_, /^(\d+)/ ? $1 : -1 ] }
/^(.*\n?)/mg;
}
@ARGV
содержит аргументы командной строки. Запуск программы без аргументов приводит к появлению руководства по стандартной ошибке.
$^I
содержит расширение, добавляемое к именам файлов при создании резервных копий для редактирования на месте, которое также можно включить с помощью переключателя Perl -i
, описанного в документации perlrun .
-i [расширение]
указывает, что файлы, обработанные конструкцией <>
, должны редактироваться на месте. Это делается путем переименования входного файла, открытия выходного файла с исходным именем и выбора этого выходного файла в качестве значения по умолчанию для операторов print
.
$/
- разделитель входных записей. Установка его в неопределенное значение означает, что вы хотите, чтобы последующие вызовы оператора readline считывали конец файла. Производительность пострадает при очень больших входах.
На каждой итерации цикла while
специальная переменная $_
будет содержать содержимое текущего файла в целом. Чтобы отсортировать строки, мы сначала разбиваем их на части.
Не пугайтесь print
внутри цикла. Это Schwartzian Transform , распространенная техника в Perl, хотя она дебютировала с обзорами менее восторженных . Чтобы понять, что происходит, прочитайте его с конца до начала.
- Захватить список всех строк в текущем файле. Переключатель регулярного выражения
/m
сопоставляет ^
в начале строки, а не только в начале целевой строки.
- Для каждой строки попытайтесь захватить одну или несколько цифр в начале этой строки или по умолчанию -1.
- Сортировка строк в порядке возрастания ключа сортировки.
- Наконец, напечатайте строки в отсортированном порядке. При включенном редактировании на месте
print
выводит в текущий сортируемый файл.
В более процедурном стиле вы бы записали цикл как
while (<>) {
my @lines = /^(.*\n?)/mg;
my @augmented = map { [ $_, /^(\d+)/ ? $1 : -1 ] } @lines;
my @sorted = sort { $a->[1] <=> $b->[1] } @augmented;
print map $_->[0], @sorted;
}
Как только вы понимаете, что происходит с преобразованием Шварца, все временные эффекты кажутся ненужным беспорядком.