在图案之间打印-awk



我有以下输入文件

-------------------------------------
--- A-TKE spectrum (post-neutron)---
-------------------------------------
2-dim. array: (A =  73 To  162 Step 1) (E =  122 To  198 Step 1)
(The data are written according to the loop structure specified above.
The last loop is the inner-most one. Line breaks are not related to the data structure!
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 2 0 0 1 0 0 0 0 

    </A_TKE>
  </Results>

这个文件是一个更大的文件的一部分,该文件包含更多类似于上面的数字块。

我想要做的是在一个单独的文件中打印文件中的数字。作为第一次尝试,我想"让我们打印两个模式之间的东西"。START模式为--- A-TKE spectrum (post-neutron)---, END模式为</A_TKE>

我用

awk '/--- A-TKE spectrum (post-neutron)---/{flag=1;next}/</A_TKE>/{flag=0}flag{print}' input

令我惊讶的是屏幕上什么也没有打印。知道为什么会这样吗?

我现在也想如果我可以用一个数字代替next,这个数字将对应于我想在给定模式之后打印的行

在perl中(因为您从awk开始,这也被标记为perl):

perl -ne 'print if m/post-neutron/...m/A_TKE/' input

它将做你的东西试图做的事情。

它的工作原理是使用range operator -这是一个perl结构,它测试当前文件是否在两个标记之间。

以及perl可以像awksed一样内联运行的事实。-ne表示"将此代码包装在while循环中",每次迭代一行。(例如,默认情况下sed/awk/grep)。

否则……这在一定程度上取决于else在您的文件中是什么。因为从你给出的例子中-唯一以数字开头的行是你想要的。所以:

perl -ne 'print if m/^s*d+s*d+/'

(或者结合两个测试:

perl -ne 'print if m/post-neutron/...m/A_TKE/ and m/^s*d+s*d+/'

将输出行首为number-space-number的两个文本标记之间的任何内容。

您的awk脚本差不多完成了。我将这样构建它:

awk '
  /</A_TKE>/ {exit}
  flag && NF==50 {print} 
  /--- A-TKE spectrum .post-neutron.---/ {flag=1}
' input

你当然可以优化它,但只是看看它的逻辑,这个想法是,一旦你达到你的结束标记,你不需要做进一步的处理。并且你只希望在开始标记之后开始打印。

注意,我已经用圆点替换了开始标记中的括号,因为括号被解释为正则表达式的一部分。我相信您可能正在考虑搜索这些简单的字符串,但它们是正则表达式。

工作的一些想法

Awk可以用这个简单的命令在两个匹配的行之间打印:

awk '/PATTERN1/,/PATTERN2/' file.txt

如果你想更多地控制找到行时发生的事情,你可以使用flag方法。

awk '/A-TKE/{f=1;for (i=0;i<7;i++){getline}}/A_TKE/{f=0}f' file.txt 

调整i<7以指定要跳过的行数。

此外,在这个特殊的情况下,您可以利用您有50个数字字段的事实,这在文件的其他任何地方都不太可能发生。因此,您还可以使用以下命令获得感兴趣的数字:

awk 'NF>40' file.txt

NF是一个特殊的awk变量,用于存储当前记录(行)中字段(列)的数量。

为什么你的方法不工作

您的方法不起作用,因为awk中//之间的所有内容都被视为正则表达式。在您的例子中,字符串中有几个-(),它们没有被转义,因此假定它们的特殊含义,因此您键入的表达式永远不匹配,因此标志永远不会设置为1,并且awk不打印一行。

试试这个简单的sed命令

sed -n '/A-TKE/,/</A_TKE>/p' FileName

如果您想提取仅包含数字的行

 awk 'NF && !/[a-zA-Z-]+/' input.file

将生成

 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 2 0 0 1 0 0 0 0
带有模式和智能计数器的

可以写成

awk   '//A_TKE/{exit} 
       f&&s&&s--{next} 
           f&&NF{print} 
/A-TKE spectrum/{f=1;s=7}' input.file

最新更新