MUPDF: нахождение дефированных слов в файле PDF

Сценарий оболочки

Вот черновик сценария оболочки, написанный на Perl, который будет эмулировать PTY (так что rsync должен вести себя точно так же, как и в терминале), и анализирует вывод, чтобы он мог продолжать работать. двухстрочное отображение имени файла и статуса передачи. Это выглядит так:

src/test.c
    142 100%    0.19kB/s     0:00:00 (xfr#28, to-chk=0/30)

Первая строка (имя файла, src / test.c ) будет изменяться в зависимости от текущего имени файла, выводимого rsync . Вторая строка будет изменяться всякий раз, когда rsync выводит обновленную строку состояния.

NB: Я выбрал двухстрочный дисплей (но тот, который по-прежнему не будет прокручиваться!) Вместо однострочного дисплея, поскольку, по крайней мере, при моем обычном использовании я получаю длинный путь / имена файлов это было бы слишком широко в сочетании со строкой состояния. Однако, как вы увидите ниже, было бы легко изменить объединение имени файла / пути и статуса в одну строку.

Когда rsync завершается, сценарий завершается с тем же кодом выхода (так что вы все еще можете перехватывать ошибки и т. Д.)

Обоснование

Основано на обсуждениях с OP, встроенный rsync были неадекватными, их версия rsync старше, а их потребности уникальны. Таким образом, я чувствовал, что собственный сценарий был единственным способом достичь их цели.

Другой вариант - использовать любую из множества существующих rsync утилит-оболочек «резервного копирования», которые уже существуют, хотя я не знаю ни одной, поддерживающей аналогичный вывод.

Исходный код

 #!/usr/bin/env perl

 # Custom progress wrapper for rsync

 use 5.012;
 use strict;
 use warnings;
 use autodie;
 use IPC::Run qw/run start pump finish harness/;

 my $RSYNC=`which rsync`; # Try to get rsync location from PATH
 chomp $RSYNC;

 my ($in,$out); # Input and output buffers
 my $h = harness [ $RSYNC, @ARGV ], 'pty>', \$out;

 local $| = 1; # Autoflush output
 print "\n\n\e[2A\e[s"; # Make room and save cursor position
 my ($file, $status) = ('',''); # Will hold filename and status lines

 while ($h->pump) { parse() }
 parse(); # Don't miss leftover output

 $h->finish;
 exit $h->result; # Pass through the exit code from rsync

 # Parse and display file/status lines from rsync output
 sub parse {
     for (split /[\n\r]+/, $out) {
         $file = $_ if /^\S/;
         $status = $_ if /^\s/;
         print "\e[u\e[0J$file\n$status\n";
     }
     $out = ''; # Clear output for next pump
 }

Предварительные требования

Для сценария требуются два нестандартных модуля: IPC :: Run и IO :: Pty .Оба они могут быть установлены с помощью cpan , который поставляется с Perl. Многие, в том числе и я, предпочитают cpanm , который можно установить с помощью следующего однострочника:

curl -L https://cpanmin.us | perl - App::cpanminus

Затем вы должны запустить:

cpanm IPC::Run IO::Pty

Поддерживаемые типы терминалов

Это будет работать практически в ] любой современный терминал, поскольку он использует простое перемещение курсора ANSI и коды очистки для постоянной перезаписи нескольких нижних строк экрана.

Использование

То же, что и сам rsync . Обратите внимание, что вам нужно указать - progress самостоятельно, но вы можете легко отредактировать некоторые аргументы по умолчанию, изменив строку $ h = harness ... :

 my $h = harness [ $RSYNC, '--progress', @ARGV ], 'pty>', \$out;

rsync ] расположение двоичного файла

Сценарий пытается автоматически определить расположение двоичного файла rsync с помощью , который , который будет работать почти во всех средах. Вы также можете отредактировать строку my $ RSYNC = '...' , чтобы указать произвольное местоположение, если это необходимо или требуется (важно: замените обратные кавычки (`) на одинарные кавычки (' ) в этом случае.)

Устранение неполадок / расширение

Вывод ошибок специально не обрабатывается, но может быть с некоторыми незначительными изменениями в сценарии.

Несмотря на достаточную надежность, очевидно, что это «быстрое» усилие, которое не может учесть все возможные результаты работы невероятно сложной утилиты rsync . Возможно, вам придется в некоторой степени адаптировать его под свои нужды, что, будем надеяться, достаточно просто: весь вывод поступает в переменную $ out , которую вы можете обработать в соответствии со своими потребностями.

Преобразование в однострочное отображение вместо двухстрочного

Как упоминалось выше, я выбрал двухстрочный дисплей без прокрутки , чтобы лучше отображать длинные пути. Однако преобразование вывода в однострочное отображение тривиально. Просто измените строку print ... в подпрограмме parse () на что-то вроде этого:

    printf "\e[u\e[0J%-30.30s %s\n", $file, $status;

или, чтобы полностью отказаться от кодов перемещения ANSI:

    printf "\r%-30.30s %-40.40s", $file, $status;
    STDOUT->flush; # $| = 1 won't help you here

Затем вы Вместо этого вы увидите что-то вроде этого:

src/test.c               142 100%    0.19kB/s     0:00:00 (xfr#28, to-chk=0/30)

Вы могли заметить, что % - 30.30s - это довольно произвольная ширина printf , и вы были бы правы. Вы можете использовать что-то вроде ответа из этого вопроса , чтобы получить ширину терминала, чтобы вы могли соответственно увеличивать / уменьшать этот размер.

2
19.09.2018, 14:11
3 ответа

Поиск слова в PDF на самом деле является функцией программы просмотра. Таким образом, каждый зритель по-своему подходит к тому, с чем он будет работать. На практике я обнаружил, что Okular был лучшим выбором среди всех просмотрщиков PDF, которые я тестировал. Насколько мне известно, Mupdf не может обрабатывать слова через дефис.

2
27.01.2020, 21:52

Обратите внимание, что PDF-файл содержит не исходный текст, а описание, какие глифы куда ставить. Поиск текста в PDF зависит от (1 )PDF, имеющего таблицу (s ), которая описывает, какие глифы соответствуют каким символам Юникода (2 )способ повторной сборки этих переведенных символов в слова (3 )предположения о том, как работало генерирующее приложение, например проставьте глифы в текстовом порядке (, что, например.произойдет ужасный сбой, когда текст двух столбцов -отображается в обоих столбцах одновременно ).

Чтобы учесть переносы, вам нужно реализовать алгоритм, который обнаруживает тире в конце строки (для этого можно использовать разные глифы ), а затем объединяет слово (и берет специальные правила о hypenation во внимание, например для немецкого языкаck).

Так что да, это можно сделать, но не так просто, и тогда это все равно будет работать только для некоторых языков/скриптов.

3
27.01.2020, 21:52

Я не знаю, как это сделать внутри MuPDF, но один из способов получить эти строки/совпадения — отфильтровать их с помощьюpdftotext

 pdftotext file.pdf - | grep 'meaningless'

По умолчанию pdftotext расставляет строки без переносов.

2
27.01.2020, 21:52

Теги

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