awk: 패턴 1 아래 2줄에서 시작하여 조건으로 끝나는 일련의 줄 사이의 열에서 문자열의 발생 횟수를 셉니다.

awk: 패턴 1 아래 2줄에서 시작하여 조건으로 끝나는 일련의 줄 사이의 열에서 문자열의 발생 횟수를 셉니다.

수천 줄의 입력 파일이 있습니다. 파일에서 /mo/ 패턴의 첫 번째 인스턴스가 포함된 섹션에 관심이 있습니다. 이 패턴을 검색하고 코드를 실행한 다음 mo 또는 다른 줄의 다른 패턴 이전에 코드를 중지해야 합니다.

다음과 같습니다.

 >>>>>          -0.2834320000         -0.9672660000          0.0000000000  6.0 C
 m.o. irrep     orbital         orbital       orbital
              energy (a.u.)   energy (e.v.)   occupancy
========================================================
  1     1    -20.63710689       -561.5697        2.0000
  2     1    -20.58909944       -560.2634        2.0000
  3     1    -11.45645851       -311.7491        2.0000
  4     1    -11.29965696       -307.4823        2.0000
  5     1    -11.29203148       -307.2748        2.0000
  6     1     -1.44555716        -39.3360        2.0000
  7     1     -1.35738379        -36.9367        2.0000
  8     1     -1.07586111        -29.2760        2.0000
  9     1     -0.91591305        -24.9235        2.0000
 10     1     -0.75492584        -20.5428        2.0000
 11     1     -0.71126523        -19.3547        2.0000
 12     1     -0.70828880        -19.2737        2.0000
 13     2     -0.62802299        -17.0895        2.0000
 14     1     -0.61775719        -16.8102        2.0000
 15     2     -0.50208166        -13.6625        2.0000
 16     1     -0.49193707        -13.3864        2.0000
 17     1     -0.43731872        -11.9002        2.0000
 18     2     -0.43546575        -11.8497        2.0000
 19     2      0.07335689          1.9962        0.0000

표적

  1. 패턴 /mo/(여기서 $1=1) 아래에서 3줄을 시작합니다.
  2. $2가 "1"과 같지 않은 횟수를 세어보세요(다른 파일에서는 $2가 3 또는 4일 수도 있으므로 $2!= 1로 계산해야 합니다).
  3. 개수는 $3가 음수인 행 범위 내에 있어야 합니다. 즉, 밑에서 두 번째 줄까지.

/====/ 패턴은 문서의 앞부분에 나타나므로 사용할 수 없습니다.

  • 출력은 3이어야 합니다. $3이 음수인 행 범위 내에는 $2가 1이 아닌 행이 3개 있습니다.

시도

사용할 부분 코드를 제공하는 다른 답변을 온라인에서 검색했습니다. 예:

  • 내 시작선을 패턴 + 3(원천):

    awk '/m.o./{n=NR+3}n
    
  • $2 != "1" (원천)

    awk '$2!="1"{++count}
    
  • 나를 정의하는 마지막 줄은 다음과 같습니다.

    awk '{if ($3 > 0){print count; exit}
    

하지만 이 모든 것을 어떻게 하나로 합칠지는 모르겠습니다. 중요한 것은 어떻게든 최종 $2에서 추가 2를 계산하는 것을 피해야 한다는 것입니다.

나는 확실히 위의 코드를 다시 작성할 의향이 있습니다. 나는 명확성을 위해 몇 가지 예를 제공하고 싶었습니다.

감사해요.

답변1

와우 나는 마침내 다음 줄로 그것을 알아 냈습니다.

 awk '$1 ~ /m.o./ { n=NR+3}n && $3+0 > 0 { n=0 } {if ( n != 0 && $2 != "1" && $3+0 < 0) { count++; }} END { print count }' input

이전의 문제는 각 명령문이 전체 문서에서 독립적으로 작동하는 것처럼 보였기 때문에 특정 범위 내에서만 조건이 작동하도록 강제할 수 없었기 때문에 원하지 않는 다른 많은 행을 계산하게 되었습니다. 세다. 3의 정답보다 더 큰 값이 계속 나오네요.

예를 들어, 웹에서 이 문제에 대한 일반적인 솔루션인 것으로 보이는 플래그를 사용하면 플래그가 해당 행에서 활성화되지 않거나 플래그에서 허용하는 행 범위 밖에서 계산이 발생합니다. 내 스키마에도 속하지 않는 행을 계산하고 있습니다. Inian은 >>>> 패턴(어떤 이유로든 개수 일치를 반환함)이 있는 행을 제외하도록 코딩되어 있지만 일치하지 않는 다른 패턴이 있으며 문서에서 모든 20,000개 행에 대한 패턴을 찾는 것은 불합리합니다.

이것은 마침내 나를 위해 일했습니다.

 $1 ~ /m.o./ { n=NR+3}n

이는 "mo"를 포함하는 $1의 첫 번째 인스턴스에서 시작하도록 스크립트를 설정합니다. 스크립트에 mo 패턴이 두 번째로 나타나는 것을 방지하려면 $1을 지정해야 합니다. 다행히 두 번째 인스턴스는 $2에 있으므로 $1만 일치시켜 이를 방지합니다. 둘 다 같은 열에 있으면 어떻게 피할 수 있는지 모르겠습니다.

일치점에서 n은 라인번호(NR)에 괄호 안의 3을 더한 값으로 정의한 후 다시 괄호 바깥에 추가하여 기록한다. 이렇게 하면 awk를 사용하여 패턴과 여러 줄로 시작할 수 있는 것 같습니다.

  && $3+0 > 0 {n=0}

이를 통해 패턴을 일치시키는 대신 변수 조건을 기반으로 줄 범위를 끝낼 수 있습니다(웹의 다른 많은 솔루션에서는 /pattern/을 사용하여 정의된 문자열 패턴을 일치시켜 줄 범위의 끝을 정의하지만 여기에서 어떻게 적응하는지 알아보세요.)

나는 &&가 시작점을 바인딩하기 위해 이전 패턴 일치를 유지하고 $3 > 0(내 조건)인 문서의 모든 후속 지점에 대해 n이 0이 된다고 믿습니다.

마지막으로 시작선과 끝선을 묶는 방법이 생겼습니다.

이제 해당 범위 내에서 조건에 따라 행 수를 계산하는 기능을 적용할 수 있습니다.

   {if ( n != 0 && $2 != "1" && $3+0 < 0) { count++; }}

첫 번째 항목을 호출하여 행 범위 내에서 유지합니다. n이 0이 아닌 경우 이는 내 패턴 일치와 내가 설정한 조건 사이의 경우입니다. 이 행 범위 내에서 스크립트는 $2가 1이 아니고 $3이 음수인 행을 추출합니다. 각 인스턴스마다 내 count 변수가 1씩 증가합니다.

   END { print count }' input

스크립트 마지막에는 입력 파일의 변수 개수 합계가 인쇄됩니다.

답변2

이를 수행하는 방법에는 여러 가지가 있지만 아마도 가장 간단하고 이해하기 쉬운 방법은 다음과 같습니다.

계산할 행을 선택하는 복잡한 조건을 만들 수 있습니다.

awk 'BEGIN { total=0 } NR > 3 && $2 != 1 && $3 < 0  { total++ } END { print total }' 

또는 코드 블록에 조건을 넣을 수 있습니다.

awk 'BEGIN { total=0 } NR > 3 { if ( $2 != 1 && $3 < 0 ) { total++ } } END { print total }' 

답변3

다음과 같이 시도해 볼 수 있습니다.

awk '$1=="m.o."{if(l){exit};l++;next}l&&l<3{l++;next}l{if($3<0&&$2!=1)c++}END{print c}' infile

관련 정보