여러 줄 정규 표현식(grep, sed, awk, perl)

여러 줄 정규 표현식(grep, sed, awk, perl)

여러 줄 정규식이 수십 번 논의되었다는 것을 알고 있지만 내 패턴에 맞게 작동할 수는 없습니다.

나는 설명하려고 노력할 것이다. 내 디렉토리에 일부 텍스트 파일이 있습니다. 파일의 텍스트 예:

LINE OF TEXT 2
LINE OF TEXT 1
LINE OF TEXT 3

LINE OF TEXT 1
LINE OF TEXT 2
LINE OF TEXT 3

LINE OF TEXT 1
LINE OF TEXT 3

LINE OF TEXT 3
LINE OF TEXT 2
LINE OF TEXT 1

LINE OF TEXT 2
LINE OF TEXT 3

"LINE OF TEXT 1"(사이에 빈 줄 없음) 뒤에 오는 "LINE OF TEXT 2" 뒤에 오는 "LINE OF TEXT 3"을 찾고 싶습니다.

각 줄 자체는 정규식이어야 합니다(예: "LINE"으로 시작하고 특정 숫자로 끝나는 줄).

참고: 모든 파일에 정확한 행 순서가 포함되어 있는 것은 아니므로 패턴이 일치하면 패턴이 인쇄되지 않고 파일 이름만 STDOUT에 인쇄됩니다.

한 줄 정규식으로 이 작업을 수행할 수 있습니까? 예를 들어 awk는 파일에서 패턴을 검색하고 패턴이 발견되면 파일 이름을 STDOUT에 인쇄합니다. 그런 다음 "find -exec"와 함께 이 정규식을 사용할 수 있습니다.

언급된 모든 도구(grep, awk, sed 또는 perl)가 가능합니다.

답변1

Awk를 사용하여 "Record Separator" 변수를 최소 두 개의 연속 개행 문자와 일치하는 정규식으로 설정하여 이 작업을 수행할 수 있습니다.

awk -v RS='\n\n+' '/1.*2.*3/' file.txt

필드 구분 기호를 단일 개행 문자로 설정할 수도 있습니다.

awk -v RS='\n\n+' -F '\n' '$1 == "LINE OF TEXT 1" && $2 == "LINE OF TEXT 2" && $3 == "LINE OF TEXT 3"' file.txt

읽기 쉽도록 분류:

awk -v RS='\n\n+' -F '\n' '
  $1 == "LINE OF TEXT 1" &&
  $2 == "LINE OF TEXT 2" &&
  $3 == "LINE OF TEXT 3"
' file.txt

일치하는 항목이 발견된 경우에만 파일 이름을 인쇄하도록 하려면 다음을 수행할 수 있습니다.

awk -v RS='\n\n+' -F '\n' '
  $1 == "LINE OF TEXT 1" &&
  $2 == "LINE OF TEXT 2" &&
  $3 == "LINE OF TEXT 3" {
    match++
  }
  END {
    if (match) {
      print FILENAME
    }
' file.txt

하지만 당신이 말하는 것을 고려하면find와 함께awk, 종료 상태와 인쇄에는 Awk를 사용하는 것이 좋습니다 find.

find . -type f -exec awk -v RS='\n\n+' -F '\n' '
  $1 ~ /LINE OF TEXT 1/ &&
  $2 ~ /LINE OF TEXT 2/ &&
  $3 ~ /LINE OF TEXT 3/ {
    exit 0
  }
  END { exit 1 }
' {} \; -print

이렇게 하고 싶은 일이 있으면기타find인쇄하기 전에 이미 이 작업을 수행할 준비가 되어 있습니다 (다른 주요 작업).

답변2

Perl에서는 "단락 모드"를 사용할 수 있습니다. 이 모드는 개행으로 구분된 여러 청크로 파일을 읽습니다. 입력 레코드 구분 기호로 빈 문자열을 설정하면 됩니다 $/.

perl -lne 'BEGIN { $/ = "" }
       $found = 1 if /^LINE.* 1\nLINE.* 2\nLINE.* 3$/m;
       if (eof) { print $ARGV if $found; undef $found }
' -- file1 file2...
  • eof모든 파일의 끝에서 true
  • $ARGV현재 열려 있는 파일의 이름입니다.

답변3

함께 작동하는 find<->perl 조합을 사용하여 이 작업을 수행할 수 있습니다. 예를 들면 다음과 같습니다.

find . -type f -exec \
  perl -l -0777ne '/^LINE.* 1\nLINE.* 2\nLINE.* 3$/m && print $ARGV' {} +

관련 정보