Вы можете найти каждый файл для обработки с помощью find
и передать каждое имя файла в сценарий, специально созданный для поиска совпадения и печати имени файла в случае совпадения; Я бы предложил использовать сценарий, а не однострочник, чтобы облегчить обработку многострочной строки по сравнению с подсказкой.
То есть:
find . -name "*.[ch]" -exec /path/to/script {} \;
Где сценарий
- это сценарий Perl:
#! /usr/bin/perl
$/ = ""; # sets the input record separator to an empty string
$_ = <>; # stores the content of the file specified in the first argument in $_
$string = <<EOF; # The multi-line string to match starts here
My
multiline
string
EOF
# The multi-line string to match ends here
/\Q$string\E/ && print($ARGV."\n"); # If $_ matches $string, prints the name of the file
$ / = "";
: устанавливает разделитель входных записей Perl на пустую строку; это приводит к тому, что Perl сразу читает весь файл, указанный в первом аргументе сценария; $ _ = <>;
: сохраняет содержимое файла, указанного в первом аргументе в $ _
; $ string = << EOF;
[...] EOF
: сохраняет содержимое [...] в $ string
(замените [...] на соответствующую многострочную строку); / \ Q $ string \ E / && print ($ ARGV. "\ n");
: if $ _
соответствует $ string
, печатает имя файла. Это пример вывода тестовой иерархии каталогов, созданный специально:
% for f in *; do printf '%s:\n\n' "$f"; <<<'' cat "$f" -; done
file1:
My
multiline
string
file2:
My
multiline
string
file3:
My
other
multiline
string
script.pl:
#! /usr/bin/perl
$/ = "";
$_ = <>;
$string = <<EOF;
My
multiline
string
EOF
$string = quotemeta($string);
/$string/&&print($ARGV."\n");
% find . -type f -exec ./script.pl {} \;
./file2
./file1
regex2=$'\x28'
точно эквивалентен regex2='('
, оболочка обрабатывает кавычки $'...'
, когда происходит присваивание. И (
сам по себе является недопустимым регулярным выражением, поэтому [[ =~ ]]
сообщает об ошибке, возвращая статус выхода2
:
$ re='('; [[ "(" =~ $re ]]; echo "$?"
2
(Конечно, внутри инструкции if
вы не можете отличить код выхода 1
для "нет совпадения" и 2
для "ошибки", но она есть.)
Вам нужно избежать открывающей скобки из регулярного выражения:
$ re='\('; [[ "(" =~ $re ]] && echo match
match
или поместите его в группу квадратных скобок:
$ re='[(]'; [[ "(" =~ $re ]] && echo match
match
При быстром тестировании регулярные выражения Bash не поддерживают экранирование шестнадцатеричных или восьмеричных символов, поэтому re='\050'
или re='\x28'
не работают.