패턴 옆이나 아래에 있는 단어를 찾아야 합니다.

패턴 옆이나 아래에 있는 단어를 찾아야 합니다.

다음 줄이 포함된 파일이 있습니다.

    .......... FROM ABCD_EXT
    .......... FROM HEG_EXT1 
.......... from
           xyz_EXT
.......... FROM abd_EXT2 
..........where QWT_EXT.SID=POI_EXT.GET
..........where QWT_EXT.SID=POI_GET.END_EXT

"FROM"(대소문자 구분 안 함) 옆이나 아래에 있고 _EXT로 끝나는 단어를 grep하면 됩니다.

즉, 예상되는 출력은 다음과 같습니다.

ABCD_EXT 
xyz_EXT

편집: 예, 같은 줄에 나타나든 다음 줄에 나타나든 'from' 뒤의 다음 단어를 grep해야 합니다.

나는 이것을 시도했고 첫 번째 부분을 올바르게 얻었습니다(같은 줄).

grep _EXT rt.sql |grep -i from|sed -e 's/_EXT/_EXT /g'|awk '{print $NF}'|grep _EXT

아래 줄에서 단어를 얻는 것이 문제입니다.

답변1

그리고 pcregrep:

pcregrep -Mo1 '(?<!\S)(?i:from)\s+(\S*_EXT)(?!\S)' < rt.sql
  • -MM여러 줄 모드 의 경우
  • -o1첫 번째o 캡처 그룹 과 일치하는 콘텐츠를 출력합니다 .1
  • \s공백 문자(적어도 공백, 탭, CR 및 LF 포함)와 일치하고 \S공백이 아닌 문자와 일치합니다.
  • x+: 1개 이상의 xs 와 일치
  • x*: 0개 이상의 xs와 일치합니다.
  • (?i:from): from, 대소문자를 구분하지 않으며 와 동일합니다 [fF][rR][oO][mM].
  • (?<!\S): 공백이 아닌 경우 또는 IOW에 대한 부정적인 뒤돌아보기전제는 이전 내용이 비어 있지 않다는 것입니다.(공백이나 주제의 시작 부분에도 동일하게 적용됩니다).
  • (?!\S): 똑같지만 뒤가 아니라 앞을 바라봅니다. SQL이라면 ;허용하고 싶을 수도 있습니다.(?![^\s;])

해당 항목이 없으면 pcregrep( 의 첫 번째 항목 perl)을 사용하여 전체 파일을 연기할 수 있습니다.ppcregrep-0777

perl -l -0777 -ne 'print for /(?<!\S)(?i:from)\s+(\S*EXT)(?!\S)/g' < rt.sql

또는 GNU를 사용하여 grepPCRE 지원으로 구축된 경우(이것은 -P일치를 위해 Perl과 같은 정규식을 사용하는 옵션을 추가합니다):

grep -zPo '(?<!\S)(?i:from)\s+\K\S*EXT(?!\S)' < rt.sql | tr '\0' '\n'

GNU는 첫 번째 캡처 그룹 일치 항목 의 인쇄를 grep지원하지 않기 때문에 대신 일치 항목의 전체 내용을 인쇄하지만 일치 항목으로 무엇을 eep할지를 매처에게 알려줍니다 .-o<n>n-o\KK

행이 아닌 NUL로 구분된 레코드를 처리 하므로 -z입력에 NUL이 포함되어 있지 않다고 가정하면(일반적으로 SQL 및 텍스트의 경우에 해당해야 함) 이는 파일의 전체 내용을 구성하는 하나의 레코드일 것입니다. Perl에서와 같이 위의 후루룩 패턴입니다. 그러나 출력 레코드 구분 기호도 NUL이므로 tr각 일치 항목이 별도의 줄에 있도록 이를 줄 바꿈으로 변환해야 합니다.

답변2

GNU 사용sed

$ sed -En 'N;s/.*from( ([^_]*_ext\>)[^\n]*\n.*|\n.* ([[:alpha:]]+_ext\>))/\2\3/Ip' input_file
ABCD_EXT
xyz_EXT

답변3

샘플 데이터로 시도해 보세요 datafile.

> awk -v printfirst=0 'BEGIN {IGNORECASE=1}
                       {if (printfirst == 1) {
                           print $1; printfirst=0; next
                                             }
                       } 
                       {for (i=1;i<=NF;i++) 
                           if ($i ~ /^from$/) {
                               if (i == NF) {printfirst=1} 
                               else if ($(i+1) ~ /_EXT$/) {print $(i+1)}
                           }
                       }' datafile

ABCD_EXT
xyz_EXT
> _

이를 수행하는 방법에는 여러 가지가 있습니다 awk(여기 Awk의 GNU 버전이 있습니다). 나는 편의를 위해 그리고 입력 파일을 두 번 구문 분석하는 것을 피하기 위해 이것을 선택했습니다.

  • -vAwk에 변수를 전달하기 위한 플래그입니다. 변수를 printfirst0으로 초기화하고,
  • BEGIN {IGNORECASE=1}Awk 검색 패턴에서 대소문자를 구분하지 않도록 설정
  • 첫 번째 {}블록: 첫 번째 Awk 필드를 조건부로 인쇄합니다. 즉, 레코드 $1로 점프합니다.next
  • 두 번째 블록 {}: 구문 분석된 레코드 from의 경우 대소문자를 구분하지 않고 각 필드를 일치시키려고 합니다.
    • 일치하는 항목이 없으면 아무 작업도 수행하지 않습니다.
    • 일치하는 경우:
      • 일치하는 필드가 레코드의 마지막 필드인 경우 awk 내부 변수를 printfirst1로 설정하고 다음 레코드로 이동합니다.
      • 일치하는 필드가 레코드의 마지막 필드가 아닌 경우 레코드의 다음 필드를 인쇄합니다.

관련 정보