Как превратить однострочную версию Perl grep в псевдоним?

Известная ошибка:

https://bugs.exim.org/show_bug.cgi?id=2250

Исправление тестируется прямо сейчас, но обходным путем является отключение PIPELINING с помощью:

конвейерная обработка _реклама _hosts =

(т.е. пустой список)

0
05.02.2020, 10:26
2 ответа

aliasв bashне предназначены для приема аргументов и не будут знать, что с ними делать, если они предоставлены. Как правило, их следует избегать и использовать только для действительно простых альтернатив имени команды.

Вместо этого рекомендуется использовать функцию. Обратите внимание, что pgrep— допустимый бинарный файл Linux, который не следует использовать. Вместо этого рекомендуется использовать недвусмысленное имя.

perlgrep() {
    perl -wnle "/$1/ and print"
} 

и теперь назовите его

perlgrep '^.{0,80}$'

Причина вашей ошибки в том, что, поскольку aliasне мог передать сам аргумент, когда произошло раскрытие, команда стала такой

grep -ri someText * | perl -wnle "/$1/ and print" '^.{0,80}$'

, что неверно, потому что perlсчитает '^.{0,80}$именем файла, который необходимо открыть и запустить регулярное выражение.

5
28.04.2021, 23:24

Обратите внимание, чтоpcregrep(из библиотеки PCRE)и GNUgrep -P(при сборке с поддержкой PCRE )могут принимать Perl -как регулярные выражения, а grep -Pбудет нормально работать в UTF -8 данных в UTF -8 локалей.

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

Вы могли бы сделать:

perlgrep() (
  export RE="${1?}"; shift
  exec perl -Mopen=locale -Twnle '
    BEGIN {$ret = 1; $several_files = @ARGV > 1}
    if (/$ENV{RE}/) {
      $ret = 0;
      print $several_files ? "$ARGV: $_" : $_
    }
    END {exit $ret}' -- "$@"
)

Но остерегайтесь последствий запуска perl -nдля файлов с произвольными именами , которые лишь частично смягчаются опцией -Tвыше.

Кроме того, с помощью -Mopen=localeмы декодируем ввод и кодируем вывод в соответствии с кодировкой локали, но сами имена файлов будут закодированы , но не декодированы , что означает, что если имена файлов имеют значения байтов выше 127, это не будет работать должным образом, если кодировка локали не iso8859 -1.

В конце концов, вам просто нужно декодировать строки ввода только для сопоставления. Вам не нужно перекодировать его, а не декодировать/кодировать имена файлов.

Вместо этого в последних версиях perlможно было бы:

#! /usr/bin/perl --
use warnings;
use strict;
use Encode::Locale;
use Encode;

my $re = shift @ARGV;
my $several_files = @ARGV > 1;
my $ret = 1;

while (<<>>) {
  if (decode(locale => $_) =~ $re) {
    $ret = 0;
    print $several_files ? "$ARGV: $_" : $_
  }
}
exit $ret;

Чтобы предотвратить внедрение произвольного кода из аргументов, операторы регулярных выражений, такие как (?{code}), (??{code}), отключены. Если вы хотите их вернуть, вы можете добавить use re 'eval';вверху этого скрипта.

2
28.04.2021, 23:24

Теги

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