【问题标题】:Awk While and For Loopawk while 和 for 循环
【发布时间】:2014-01-09 16:43:46
【问题描述】:

我有两个文件(file1 和 file2)

file1:

-11.61
-11.27
-10.47

file2:

NAME
NAME
NAME

我想使用 awk 来搜索文件 2 中第一次出现的 NAME 并在它之前添加 file1 的第一行,依此类推。所需的输出是

########## Energy:              -11.61
NAME
########## Energy:              -11.27
NAME
########## Energy:              -10.47
NAME

我试过这段代码

#!/bin/bash

file=file1
while IFS= read line
do
        # echo line is stored in $line
        echo $line
awk '/MOLECULE/{print "### Energy: "'$line'}1' file2` > output
done < "$file"

但这是我得到的输出

########## Energy:              -10.47
NAME
########## Energy:              -10.47
NAME
########## Energy:              -10.47
NAME

我不知道为什么脚本在 file2 中每次出现 NAME 之前只放置 file1 的最后一个值。

感谢您的帮助!

抱歉,如果我的问题不清楚。以下是我的文件示例(energy.txt 和 sample.mol2):

[用户]$cat energy.txt

-11.61
-11.27
-10.47

[用户]$cat sample.mol2

@<TRIPOS>MOLECULE
methane
5 4 1 0 0 
SMALL
NO_CHARGES


@<TRIPOS>ATOM
  1 C        2.8930    -0.4135    -1.3529 C.3   1 <1>   0.0000 
  2 H1       3.9830    -0.4135    -1.3529 H     1 <1>   0.0000 
  3 H2       2.5297     0.3131    -0.6262 H     1 <1>   0.0000 
  4 H3       2.5297    -1.4062    -1.0869 H     1 <1>   0.0000 
  5 H4       2.5297    -0.1476    -2.3456 H     1 <1>   0.0000 
@<TRIPOS>BOND
  1   1   2  1   
  2   1   3  1   
  3   1   4  1   
  4   1   5  1   

@<TRIPOS>MOLECULE
ammonia
4 3 1 0 0 
SMALL
NO_CHARGES


@<TRIPOS>ATOM
  1 N        8.6225    -3.5397    -1.3529 N.3   1 <1>   0.0000 
  2 H1       9.6325    -3.5397    -1.3529 H     1 <1>   0.0000 
  3 H2       8.2858    -2.8663    -0.6796 H     1 <1>   0.0000 
  4 H3       8.2858    -4.4595    -1.1065 H     1 <1>   0.0000 
@<TRIPOS>BOND
  1   1   2  1   
  2   1   3  1   
  3   1   4  1   

@<TRIPOS>MOLECULE
water
3 2 1 0 0 
SMALL
NO_CHARGES


@<TRIPOS>ATOM
  1 O        7.1376     3.8455    -3.4206 O.3   1 <1>   0.0000 
  2 H1       8.0976     3.8455    -3.4206 H     1 <1>   0.0000 
  3 H2       6.8473     4.4926    -2.7736 H     1 <1>   0.0000 
@<TRIPOS>BOND
  1   1   2  1   
  2   1   3  1

这是我需要的输出

########## Energy:              -11.61
@<TRIPOS>MOLECULE
methane
5 4 1 0 0 
SMALL
NO_CHARGES


@<TRIPOS>ATOM
  1 C        2.8930    -0.4135    -1.3529 C.3   1 <1>   0.0000 
  2 H1       3.9830    -0.4135    -1.3529 H     1 <1>   0.0000 
  3 H2       2.5297     0.3131    -0.6262 H     1 <1>   0.0000 
  4 H3       2.5297    -1.4062    -1.0869 H     1 <1>   0.0000 
  5 H4       2.5297    -0.1476    -2.3456 H     1 <1>   0.0000 
@<TRIPOS>BOND
  1   1   2  1   
  2   1   3  1   
  3   1   4  1   
  4   1   5  1   
########## Energy:              -11.27
@<TRIPOS>MOLECULE
ammonia
4 3 1 0 0 
SMALL
NO_CHARGES


@<TRIPOS>ATOM
  1 N        8.6225    -3.5397    -1.3529 N.3   1 <1>   0.0000 
  2 H1       9.6325    -3.5397    -1.3529 H     1 <1>   0.0000 
  3 H2       8.2858    -2.8663    -0.6796 H     1 <1>   0.0000 
  4 H3       8.2858    -4.4595    -1.1065 H     1 <1>   0.0000 
@<TRIPOS>BOND
  1   1   2  1   
  2   1   3  1   
  3   1   4  1   
########## Energy:              -10.47
@<TRIPOS>MOLECULE
water
3 2 1 0 0 
SMALL
NO_CHARGES


@<TRIPOS>ATOM
  1 O        7.1376     3.8455    -3.4206 O.3   1 <1>   0.0000 
  2 H1       8.0976     3.8455    -3.4206 H     1 <1>   0.0000 
  3 H2       6.8473     4.4926    -2.7736 H     1 <1>   0.0000 
@<TRIPOS>BOND
  1   1   2  1   
  2   1   3  1

【问题讨论】:

  • 如果您在输入和输出中发布“NAME”的一些实际值,而不是多次重复“NAME”这个词,您的问题会更清楚。
  • 现在,您希望输出是什么?
  • 我刚刚更新了所需的输出。谢谢

标签: bash awk


【解决方案1】:

使用 awk:

awk 'NR==FNR{a[NR]=$0;next} /@<TRIPOS>MOLECULE/
    {print "########## Energy:             ", a[++i]}1' energy.txt sample.mol2

说明:

  • FNR - 当前文件的行号
  • NR - 两个文件的总行数。
  • NR==FNR{a[NR]=$0;next}申请第一个energy.txt
  • 所以上面的语句填充了一个数组,索引为1,2,3...,值为$0
  • /@&lt;TRIPOS&gt;MOLECULE/ 搜索在第二个文件上执行 sample.mol2
  • 当上述搜索成功时,它会打印带引号的静态字符串和从第一个文件创建的数组中的一行
  • ++i 打印后将计数器移动到数组中的下一个元素

【讨论】:

  • 如果我在模式 NAME 之间有文本并在行尾添加 }1' 以打印所有内容,则只会在 file2 中打印 file1 的第一个值,并且每次都会打印两次 NAME。对不起,我缺乏知识,我会很感激这方面的帮助。谢谢!
  • 我可以尝试提供帮助,但需要更好地理解您的输入文件。您能否编辑您的问题并提供这种新的 inout 数据格式,以便我更好地理解并修复代码。
  • 感谢阿努巴瓦。我刚刚用改进的示例文件更新了我的问题。
  • 有一个改进。 @MOLECULE 现在没有被打印两次,但在 sample.mol2 中的@MOLECULE 之前仍然只打印energy.txt 的第一个值
  • 感谢您的精彩解释。
【解决方案2】:
paste -d "\n" <(sed 's/^/########## Energy:              /' file1) file2
########## Energy:              -11.61
NAME
########## Energy:              -11.27
NAME
########## Energy:              -10.47
NAME

或者,坚持使用 awk

awk '{
    print "########## Energy:              " $0
    getline < "file2"
    print
}' file1

【讨论】:

  • 如果进程替换不可用,sed '...' file1 | paste -d "\n" - file2 也应该可以工作。
  • awk 代码有效。另一方面,当我尝试在模式 NAME 之间有一些文本的文件中使用它时,只有第一个值被正确返回。
  • 嗯,你应该把它添加到你的问题中。
  • 对不起格伦,我试着举一个简单的例子。但我刚刚用我的真实问题的样本更新了我的问题。谢谢
猜你喜欢
  • 2013-06-01
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-28
  • 1970-01-01
  • 1970-01-01
  • 2015-06-16
相关资源
最近更新 更多