我有一个包含数千行的输入文件。我对其中的一个部分感兴趣,其中包含文件中模式 /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/ 下面的 3 行开始(其中 $1=1)。
- 计算$2不等于“1”的次数(在其他文件中,$2也可以是3或4,所以我需要按$2!= 1来数)。
- 该计数必须在 $3 为负数的行范围内,即。直到从底部数第二行。
无法使用模式 /====/,因为它出现在文档的前面。
- 输出应为 3。在 $3 为负数的行范围内,有 3 行 $2 不等于 1。
试图
我在网上搜索了其他答案,这些答案为我提供了要使用的部分代码。例子:
将我的起始线定义为模式加 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 编码以排除具有 >>>> 模式的行(无论出于何种原因返回计数匹配),但还有其他模式不匹配,并且在文档中找到所有 20k 行的模式是不合理的。
这最终对我有用。
$1 ~ /m.o./ { n=NR+3}n
这将脚本设置为从 $1 包含“mo”的第一个实例开始。我需要指定 $1 以避免脚本中第二次出现 mo 模式。幸运的是,第二个实例在 $2 中,所以我通过仅匹配 $1 来避免它。如果两者都在同一列中,我不知道如何避免它。
在匹配点,n 被定义为行号 (NR) 加括号中的 3,然后通过在括号外再次添加它来记录。通过这种方式,我似乎能够使用 awk 从一个模式加上任意数量的行开始。
&& $3+0 > 0 {n=0}
这允许我根据可变条件结束行范围,而不是匹配模式(网络上的许多其他解决方案使用 /pattern/ 匹配定义的字符串模式来定义行范围的末尾,我无法弄清楚如何适应这里)。
我相信 && 会维护之前的模式匹配以绑定起点,然后对于文档中之后的任何点,其中 $3 > 0(我的条件),n 变为零。
最后,我有办法绑定起始线和结束线。
我现在可以在该范围内应用我想要的函数,即根据条件计算行数。
{if ( n != 0 && $2 != "1" && $3+0 < 0) { count++; }}
我通过调用第一项来保持在我的行范围内:如果 n 不为零,这只是我的模式匹配和我设置的条件之间的情况。在此行范围内,脚本会提取 $2 不为 1 并且 $3 为负数的行。它为每个实例将我的计数变量增加 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 :
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