=encoding utf-8

=head1 NAME

App::Greple::tee - модуль для замены совпадающего текста на результат внешней команды

=head1 SYNOPSIS

    greple -Mtee command -- ...

=head1 VERSION

Version 1.02

=head1 DESCRIPTION

Модуль Greple's B<-Mtee> посылает совпавшие части текста заданной команде фильтра и заменяет их результатом команды. Идея взята из команды B<teip>. Это подобно обходу частичных данных внешней командой фильтрации.

Команда фильтрации следует за объявлением модуля (C<-Mtee>) и заканчивается двумя тире (C<-->). Например, следующая команда вызывает команду C<tr> с аргументами C<a-z A-Z> для найденного слова в данных.

    greple -Mtee tr a-z A-Z -- '\w+' ...

Приведенная выше команда преобразует все совпадающие слова из нижнего регистра в верхний. На самом деле этот пример не так полезен, потому что B<greple> может сделать то же самое более эффективно с помощью опции B<--cm>.

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

При использовании опции B<--discrete> для каждой совпадающей области текста вызывается отдельная команда. Разницу можно определить по следующим командам.

    greple -Mtee cat -n -- copyright LICENSE
    greple -Mtee cat -n -- copyright LICENSE --discrete

Строки входных и выходных данных не должны быть одинаковыми при использовании опции B<--discrete>.

=head1 OPTIONS

=over 7

=item B<--discrete>

Вызвать новую команду индивидуально для каждой сопоставленной детали.

=item B<--bulkmode>

При использовании опции <--discrete> каждая команда выполняется по требованию. Опция
<--bulkmode> option causes all conversions to be performed at once.

=item B<--crmode>

Эта опция заменяет все символы новой строки в середине каждого блока на символы возврата каретки. Возврат каретки, содержащийся в результате выполнения команды, возвращается обратно к символу новой строки. Таким образом, блоки, состоящие из нескольких строк, можно обрабатывать партиями без использования опции B<--discrete>.

=item B<--fillup>

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

=item B<--squeeze>

Объединяет два или более последовательных символов новой строки в один.

=item B<-ML> B<--offload> I<command>

Опция B<--offload> в L<teip(1)> реализована в другом модуле L<App::Greple::L> (B<-ML>).

    greple -Mtee cat -n -- -ML --offload 'seq 10 20'

Вы также можете использовать модуль B<-ML> для обработки только четных строк следующим образом.

    greple -Mtee cat -n -- -ML 2::2

=back

=head1 LEGACIES

Опция B<--blocks> больше не нужна, поскольку в модуле B<greple> реализована опция B<--stretch> (B<-S>). Вы можете просто выполнить следующее.

    greple -Mtee cat -n -- --all -SE foo

Не рекомендуется использовать опцию B<--blocks>, поскольку в будущем она может быть устаревшей.


=over 7

=item B<--blocks>

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

Например, чтобы отправить внешней команде строки, содержащие шаблон C<foo>, необходимо указать шаблон, соответствующий всей строке:

    greple -Mtee cat -n -- '^.*foo.*\n' --all

Но с опцией B<--blocks> это можно сделать следующим образом:

    greple -Mtee cat -n -- foo --blocks

С опцией B<--blocks> этот модуль ведет себя более похоже на модуль L<teip(1)> с опцией B<-g>. В остальном поведение аналогично L<teip(1)> с опцией B<-o>.

Не используйте B<--blocks> с опцией B<--all>, так как блок будет представлять собой все данные.

=back

=head1 WHY DO NOT USE TEIP

Прежде всего, всегда, когда вы можете сделать это с помощью команды B<teip>, используйте ее. Это отличный инструмент и намного быстрее, чем B<greple>.

Поскольку B<greple> предназначен для обработки файлов документов, он имеет много функций, которые подходят для этого, например, управление областью соответствия. Возможно, стоит использовать B<greple>, чтобы воспользоваться этими возможностями.

Кроме того, B<teip> не может обрабатывать несколько строк данных как единое целое, в то время как B<greple> может выполнять отдельные команды на куске данных, состоящем из нескольких строк.

=head1 EXAMPLE

Следующая команда найдет текстовые блоки внутри документа стиля L<perlpod(1)>, включенного в файл модуля Perl.

    greple --inside '^=(?s:.*?)(^=cut|\z)' --re '^([\w\pP].+\n)+' tee.pm

Вы можете перевести их с помощью сервиса DeepL, выполнив приведенную выше команду, соединенную с модулем B<-Mtee>, который вызывает команду B<deepl> следующим образом:

    greple -Mtee deepl text --to JA - -- --fillup ...

Однако для этой цели более эффективен специализированный модуль L<App::Greple::xlate::deepl>. Фактически, подсказка для реализации модуля B<tee> пришла из модуля B<xlate>.

=head1 EXAMPLE 2

Следующая команда обнаружит в документе LICENSE часть с отступами.

    greple --re '^[ ]{2}[a-z][)] .+\n([ ]{5}.+\n)*' -C LICENSE

      a) distribute a Standard Version of the executables and library files,
         together with instructions (in the manual page or equivalent) on where to
         get the Standard Version.

      b) accompany the distribution with the machine-readable source of the Package
         with your modifications.

Вы можете переформатировать эту часть, используя модуль B<tee> с командой B<ansifold>:

    greple -Mtee ansifold -rsw40 --prefix '     ' -- --discrete --re ...

      a) distribute a Standard Version of
         the executables and library files,
         together with instructions (in the
         manual page or equivalent) on where
         to get the Standard Version.

      b) accompany the distribution with the
         machine-readable source of the
         Package with your modifications.

Опция --discrete запускает несколько процессов, поэтому процесс будет выполняться дольше. Поэтому можно использовать опцию C<--separate '\r'> с C<ansifold>, которая выдает одну строку, используя символ CR вместо NL.

    greple -Mtee ansifold -rsw40 --prefix '     ' --separate '\r' --

Затем преобразуйте символ CR в NL с помощью команды L<tr(1)> или другой.

    ... | tr '\r' '\n'

=head1 EXAMPLE 3

Рассмотрим ситуацию, когда требуется выполнить поиск строк в строках, не являющихся заголовками. Например, нужно найти имена образов Docker из команды C<docker image ls>, но оставить строку заголовка. Это можно сделать с помощью следующей команды.

    greple -Mtee grep perl -- -ML 2: --discrete --all

Опция C<-ML 2:> извлекает предпоследние строки и отправляет их команде C<grep perl>. Опция --discrete необходима, поскольку количество строк ввода и вывода меняется, но поскольку команда выполняется только один раз, недостатка в производительности нет.

Если попытаться сделать то же самое с помощью команды B<teip>, то C<teip -l 2- -- grep> выдаст ошибку, поскольку количество выходных строк меньше количества входных. Однако с полученным результатом проблем нет.

=head1 INSTALL

=head2 CPANMINUS

    $ cpanm App::Greple::tee

=head1 SEE ALSO

L<App::Greple::tee>, L<https://github.com/kaz-utashiro/App-Greple-tee>

L<https://github.com/greymd/teip>

L<App::Greple>, L<https://github.com/kaz-utashiro/greple>

L<https://github.com/tecolicom/Greple>

L<App::Greple::xlate>

=head1 BUGS

Опция C<--fillup> удаляет пробелы между символами хангыля при конкатенации корейского текста.

=head1 AUTHOR

Kazumasa Utashiro

=head1 LICENSE

Copyright © 2023-2025 Kazumasa Utashiro.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
