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 ドルが負の行範囲内になければなりません。つまり、下から2行目まで。

/====/ パターンは文書の前半に表示されるため使用できません。

  • 出力は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の正解よりも大きい値が出続けますね。

たとえば、Web上でこの問題に対する一般的な解決策であると思われるフラグを使用すると、フラグがその行で有効になっていないか、フラグで許可されている行の範囲外で計算が発生します。私のスキーマにも属さない行を計算しています。 Inianは、>>>>パターン(何らかの理由でカウント一致を返します)を持つ行を除外するようにコーディングされていますが、一致しない他のパターンがあり、ドキュメント内の20,000行すべてのパターンを見つけることは不合理です。

これはついに私のために働いた。

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

これは、moを含む$ 1の最初のインスタンスから起動するようにスクリプトを設定します。スクリプトにmoパターンが2番目に表示されるのを防ぐには、$ 1を指定する必要があります。幸いなことに、2番目のインスタンスは$ 2にあるため、$ 1のみを一致させることでこれを防ぎます。どちらも同じ列にあるとどうすれば回避できるのかわかりません。

一致点では、nは行番号(NR)に括弧内の3を加えた値として定義し、再び括弧の外側に追加して記録します。これにより、awkを使用してパターンと複数行で始めることができるようです。

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

これにより、パターンを一致させるのではなく、変数条件に基づいて行範囲を終了できます(Web上の他の多くのソリューションでは、/ 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

関連情報