awk在特定字符后读取3个字符

时间:2015-10-08 14:53:51

标签: string bash awk

我有一个输出文件,其中有一部分如下所示。

================================================================================
                                       INPUT FILE
================================================================================
NAME = t-Butylvinylidene-s.inp
|  1> ! LPNO-CCSD cc-pVTZ cc-pVTZ/C UNO TIGHTSCF TIGHTOPT Grid6 NOFINALGrid NUMGRAD PAL4
|  2> 
|  3> %geom Scan
|  4> A 2 1 15 = 67, 71, 10
|  5> end
|  6> end
|  7> 
|  8> *xyz 0 1 
|  9> 6        4.053878000    -18.527907000     -3.717354000
| 10> 6        3.588474000    -18.874154000     -5.083237000
| 11> 6        2.917226000    -19.112390000     -6.132425000
| 12> 6        2.817703000    -18.178677000     -2.886206000
| 13> 1        2.133454000    -19.025647000     -2.847879000
| 14> 1        3.094894000    -17.913405000     -1.866801000
| 15> 1        2.286657000    -17.336824000     -3.329174000
| 16> 6        5.010397000    -17.327109000     -3.786851000
| 17> 1        5.368223000    -17.071145000     -2.789879000
| 18> 1        5.877217000    -17.555623000     -4.406951000
| 19> 1        4.511903000    -16.455783000     -4.209438000
| 20> 6        4.792242000    -19.727095000     -3.102721000
| 21> 1        5.654756000    -20.005483000     -3.708269000
| 22> 1        5.149078000    -19.479242000     -2.103325000
| 23> 1        4.135842000    -20.593249000     -3.030303000
| 24> 1        4.320782000    -19.183475000     -5.923829000
| 25> *
| 26> 
| 27>                          ****END OF INPUT****
================================================================================

我想读第三个和第三个最后一个字符。

|  4> A 2 1 15 = 67, 71, 10

我有以下代码来执行此操作。

read -r -a scanopt <<< $(awk '
/INPUT FILE/ { input=1;}
input && 
/geom Scan/ {getline;gsub(",",""); print $3,$8,$9,$10,"T";exit}
' OFS="\t" "$path")

输入是为了确保我找到正确的句子等 我的问题是有时线路可能不同,所以我需要的最后3个数字将处于不同的位置!一些例子是:

B 1 2 = 1.2, 2, 9
D 4 8 9 5 = 50, 60, 12

我需要第1个和最后3个字符,首先有一个恒定的位置如此简单,但是最后3个,任何想法如何做到这一切我能想到的是一个很大的循环有很多if&#39 ; S

我想要考虑的另一个问题是,如果在输入文件中有人会以不同的方式输入信息,如下所示:

 %geom Scan A 2 1 15 = 67, 71, 10
end

 %geom Scan 

A 2 1 15 = 67, 71, 10
end

所以我实际上需要从遇到%geom scanend时逐字处理。现在我一行一行地做了!

2 个答案:

答案 0 :(得分:3)

我猜你的意思是第三个和最后三个字段?

awk '{print $3, $(NF-2), $(NF-1), $NF}' 

会这样做。

对于其他要求,我认为这应该有用

awk '     /end/{f=0} 
   /%geom Scan/{f=1;sub(/^.*%geom Scan/,"")} 
        f&&NF>3{print $3,$(NF-2),$(NF-1),$NF}' 

更新以修剪标题行和保护字段计数。

答案 1 :(得分:2)

关键是知道你可以依靠99.9%以及你在输入中不能得到什么。并且知道awk也允许“从最后”挑选字段。

在我看来,你总是可以依靠感兴趣的线条(并且只有那些线条)来包含模式[数字] [可选空格] [等号]。如果这是真的,这应该有效:

awk '/[0-9]\s*=/{print $3, $(NF-2), $(NF-1), $NF, "T"; exit}'

对于你的第二种情况,你需要在之前添加第二种模式(首先捕捉它):

awk '/%geom Scan .*=/{print $5, $(NF-2), $(NF-1), $NF, "T"; exit}
     /[0-9]\s*=/{print $3, $(NF-2), $(NF-1), $NF, "T"; exit}'