나는 다음에서 영감을 받아 파일 집합에서 모든 SQL 문을 awk
찾기 위해 범위 패턴을 사용하려고 합니다 .select
이 stackoverflow 답변.
awk
매뉴얼 에서 :
표현의 형태를
pattern1, pattern2
일컫는다.범위 모드. 일치하는 레코드로 시작하여pattern1
일치하는 레코드를pattern2
포함하여 모든 입력 레코드를 일치시킵니다.
내 초기 시도는
awk '/select/,/from/' *
이 경우에는 *
다양한 파일이 많이 표시됩니다.
이로 인해 select
HTML 태그에 잘못된 히트가 반환되었으므로 다음과 같이 명령을 개선했습니다.
awk '/[^<]select[^>]/,/from/' *
이렇게 하면 대부분의 클릭이 제거되는 것 같습니다.
그러나 주석에 "select"라는 단어가 나타나기 때문에 여전히 일부 잘못된 적중이 발생하며 이러한 적중은 "from"의 마지막 적중 또는 파일 끝 이전의 각 적중에서 많은 라인 노이즈로 이어집니다. 내가 원하는 것은 "select"와 "from" 사이에 10줄 이상이 있으면 범위 패턴이 일치 항목을 등록하지 않는다는 것입니다.
pattern1
내 질문은: 일치 항목과 일치 항목 사이의 행 수가 pattern2
지정된 임계값을 초과하는 경우 범위 패턴이 일치하지 않도록 할 수 있습니까? 그렇다면 어떻게 달성할 수 있나요?
답변1
범위 모드는 유용하지만 융통성이 없습니다. 이를 사용하지 말고 대신 변수 사이 또는 변수 사이의 상태를 유지하십시오. awk 스크립트 /select/,/from/
는 다음과 같습니다.
/select/ {printing = 1}
printing {print}
/from/ {printing = 0}
범위를 여러 행으로 제한하려면 표시된 행의 카운터를 유지하고 표시 여부를 결정할 때까지 출력을 누적합니다.
/select/ {select_text = $0; select_line_count = 1;}
select_line_count {select_text = select_text "\n" $0}
/from/ {if (select_line_count <= 10) {print select_text; print}
select_line_count = 0}
select
줄의 시작 부분(공백 제외)에 있어야 하고 그 뒤에 공백이 와야 하는 등 패턴을 최적화해야 할 수도 있습니다./^[\t ]*select($|[\t ])/
답변2
/pattern1/,/pattern2/
{}
이런 상황이 발생하면 실행할 블록을 추가하여 필요에 따라 조건을 확장할 수 있습니다 .
예를 들어, 50에서 70 사이의 숫자를 인쇄하면서 각 블록의 처음 5개 일치 항목만 인쇄하는 방법을 살펴보세요.
$ seq 200 | awk '/50/,/70/ {if ($0~/50/) {c=0}; if (c++ <= 5) print}'
50
51
52
53
54
55
150
151
152
153
154
155
귀하의 경우 다음과 같이 말하고 싶을 수도 있습니다. 이렇게 하면 일치하는 처음 10줄이 인쇄됩니다.
awk '/[^<]select[^>]/,/from/ {if (c++ <= 10) print}' *
더 복잡한 솔루션은 이 모든 출력을 저장한 다음 END
블록에 인쇄하는 것입니다. 이렇게 하면 특정 행뿐만 아니라 블록 자체를 제어할 수 있습니다. 데이터를 배열 등에 저장합니다.