Perl на месте сортировки строк в текстовом файле

1

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

Есть ли простой script, чтобы сделать это, желательно на месте?

Спасибо!

  • 0
    Мне кажется, что делать это на месте было бы крайне неэффективно. Сортировка требует переупорядочения, и выполнение этого на месте означает повторное перемещение всего содержимого файла. Почему вы просите сделать это на месте, а не в памяти? Вы должны указать свои потребности, а не связывать наши руки конкретным «решением», если вы хотите получить хороший ответ.
  • 2
    Вы пробовали программу сортировки? 'sort' обычно доступен на всех платформах nix.
Показать ещё 2 комментария
Теги:

3 ответа

1

Скажите, что ваш ключ сортировки - это пробег цифр в начале каждой строки, как в следующем примере.

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.

$/ - это разделитель входных данных. Установка его в значение undefined означает, что вы хотите выполнить последующие вызовы оператора readline для чтения конца файла. Производительность будет очень большой.

На каждой итерации цикла while специальная переменная $_ будет содержать содержимое текущего файла в целом. Чтобы отсортировать строки, мы сначала разделим их.

Не запугайте print внутри цикла. Это Schwartzian Transform, обычная техника в Perl, хотя она дебютировала less -это-восторженные отзывы. Чтобы понять, что происходит, прочитайте его от конца до начала.

  • Захват списка всех строк в текущем файле. Переключатель /m regex делает совпадение ^ в начале строки не только в начале целевой строки.
  • Для каждой строки попытайтесь зафиксировать одну или несколько цифр в начале этой строки или по умолчанию -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;
}

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

1

Существуют алгоритмы сортировки на месте с сложностью O (n log n), такие как Heapsort, но я не понимаю, почему вы хотели бы использовать это, а не что-то простое, например, команду Unix sort. Если у вас нет жестких требований к производительности или огромных наборов данных... но тогда, perl и python, вероятно, не лучшие инструменты для работы.

0

Для этого не существует простого script, потому что то, что вы предлагаете, на самом деле довольно сложно и неэффективно. Если ваши строки не имеют одинаковой длины в файле, это почти невозможно (или, что невероятно глупо).

Если вы абсолютно не можете сделать это в памяти и хотите сами написать код, ваш лучший подход, вероятно, сортировка слияния на диске, Пример того, как вы делаете это с ленточными накопителями, должен дать вам некоторые рекомендации.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню