수천 줄의 입력 파일이 있습니다. 파일에서 /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
표적
- 패턴 /mo/(여기서 $1=1) 아래에서 3줄을 시작합니다.
- $2가 "1"과 같지 않은 횟수를 세어보세요(다른 파일에서는 $2가 3 또는 4일 수도 있으므로 $2!= 1로 계산해야 합니다).
- 개수는 $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