=encoding utf-8

=head1 NAME

App::Greple::tee - модуль для заміни знайденого тексту на результат зовнішньої команди

=head1 SYNOPSIS

    greple -Mtee command -- ...

=head1 VERSION

Version 1.02

=head1 DESCRIPTION

Модуль B<-Mtee> у Greple надсилає частину тексту, що відповідає заданій команді фільтрації, і замінює її на результат команди. Ідея походить від команди з назвою 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<--stretch> (B<-S>) реалізовано у B<greple>. Ви можете просто виконати наступні дії.

    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
