여러 줄 문자열에 대한 디렉토리 검색

여러 줄 문자열에 대한 디렉토리 검색

여러 줄 문자열이 포함된 저장소의 모든 파일을 재귀적으로 검색하고 이를 포함하는 파일 이름을 반환하는 방법을 찾고 있습니다. 단락은 약 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

관련 정보