여러 줄 문자열이 포함된 저장소의 모든 파일을 재귀적으로 검색하고 이를 포함하는 파일 이름을 반환하는 방법을 찾고 있습니다. 단락은 약 30줄의 제목에 불과합니다. 그래서 pcregrep
여러 줄 검색이 가능하다는 것을 알고 있습니다 . 하지만 전체 표현을 넣어야 합니다. 이것은 제가 찾고 있는 긴 단락이므로 변수에 넣은 다음 해당 변수를 grep하고 싶습니다. 그래서 기본적으로 그게 다입니다. find . -name "*.[ch]" | xargs pcregrep -M $paragraph
그러나 이것은 작동하지 않습니다. 누구든지 올바른 방향으로 나를 가리킬 수 있습니까?
답변1
파일의 처음 30줄을 일치시키려고 하므로 텍스트를 파일에 저장한 ref_file
다음 이를 사용하여 diff
참조 파일을 각 파일의 처음 30줄과 비교할 수 있습니다.
find . -name "*.[ch]" -exec ./myscript {} \; -print
./myscript
어디
#!/bin/sh
head -n 30 "$1" | diff - /path/to/ref_file >/dev/null
따라서 -print
첫 번째 명령에서는 -exec
이전 명령이 평가된 경우에만 실행됩니다.진짜즉, 참조 파일의 처음 30줄과 현재 파일 사이에 차이가 없습니다.
또는 스크립트를 사용하지 않고 파일 이름을 다음 위치에 저장하려는 경우 logfile
:
find . -type f -exec sh -c 'head -n 30 "$0" | diff - /path/to/ref_file >/dev/null' {} \; -print >logfile
이것은 정확히 일치하는 항목을 찾고 있다고 가정합니다. 그렇지 않으면 차이가 하나의 공백이더라도 diff
종료됩니다 .1
답변2
처리하려는 각 파일을 찾아 find
일치 항목을 찾고 일치하는 경우 파일 이름을 인쇄하는 특별히 생성된 스크립트에 각 파일 이름을 제공할 수 있으므로 한 줄 스크립트보다는 스크립트를 사용하는 것이 좋습니다. 프롬프트 여러 줄 문자열을 쉽게 처리할 수 있습니다.
그건:
find . -name "*.[ch]" -exec /path/to/script {} \;
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");
:$_
일치하는 항목이 있으면$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