Обратный вызов grep с \ s + throwing "Нераспознанный escape \ s прошел" - PullRequest
0 голосов
/ 09 января 2019

Из моего кода Perl я хочу выполнить системный вызов

$grepp = `grep 'output\s+reg' $file`;

Но я держу

Unrecognized escape \s passed through at

Не могли бы вы помочь мне понять эту ошибку?

1 Ответ

0 голосов
/ 09 января 2019

В двойных кавычках и других подобных строковых литералах, таких как обратные метки, \ имеет значение для Perl.

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

\, за которыми следуют некоторые символы слова, имеют особое значение (например, \n приводит к переводу строки, как и \x0A). Когда за \ следует символ слова, для которого Perl не имеет значения (например, \s), вы получаете это предупреждение, потому что ваш код не совместим с форвардом. Вы можете избежать предупреждения, сделав свой код совместимым с последующим экранированием \.

my $grepp = `grep 'output\\s+reg' $file`;   # Executes: grep 'output\s+reg' some file.txt

Помимо проблемы, о которой вы спрашивали, в коде есть две основные проблемы.

Первым основным является ошибка внедрения кода. Вы вставляете текст (имя файла) в код (команда оболочки) без какой-либо формы преобразования. Это не удастся, если имя файла содержит метасимволы оболочки (например, пробел, (, ; и т. Д.), И злоумышленник может воспользоваться этой ошибкой для выполнения вредоносных команд.

String :: ShellQuote shell_quote можно использовать, чтобы избежать этой проблемы.

use String::ShellQuote qw( shell_quote );

my $cmd = shell_quote('grep', 'output\s+reg', $file);
my $grepp = `$cmd`;

Вы также можете избежать модуля и избежать создания оболочки, используя следующее:

open(my $pipe, '-|', 'grep', 'output\s+reg', $file);
my $grepp = '';
$_ .= $grepp while <$pipe>;
close($pipe);

Вторая большая проблема заключается в том, что шаблон, который вы предоставили, не означает, что вы думаете, что он делает. Язык шаблонов регулярных выражений, используемый grep по умолчанию, весьма отличается от языка Perl. Вы хотите одно из следующего:

output[[:space:]]\+reg       # Without -E or -P

или

output\s\+reg                # Without -E or -P. Less portable

или

output\s+reg                 # With -E or -P

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

use String::ShellQuote qw( shell_quote );

my $cmd = shell_quote('grep', '-E', 'output\s+reg', $file);
my $grepp = `$cmd`;

Конечно, нужно задаться вопросом, почему вы запускаете утилиту grep вместо того, чтобы выполнять поиск самостоятельно в Perl.

...