我有一个表格的文本文件:
示例输入文件
atomic structure.
created 8/4/15. author: becko
molecule name here
O 0.000000 0 0.000000 0 0.000000 0 0 0 0
C 1.422713 1 0.000000 0 0.000000 0 1 0 0
C 1.536633 1 109.666084 1 0.000000 0 2 1 0
C 1.523232 1 110.673515 1 53.747574 1 3 2 1
C 1.524902 1 110.675377 1 -51.051605 1 4 3 2
C 1.524624 1 110.815956 1 53.399712 1 5 4 3
O 1.388625 1 108.653427 1 -68.335587 1 2 3 4
O 1.418326 1 111.098351 1 58.126965 1 3 2 7
O 1.429752 1 106.981445 1 -172.599930 1 4 3 2
O 1.431727 1 110.929413 1 171.804962 1 5 4 3
C 1.389881 1 117.191086 1 95.674500 0 10 5 4
C 1.529863 1 107.679131 1 146.326675 0 11 10 5
C 1.524202 1 110.428741 1 170.992218 1 12 11 10
格式为:三个初始标题行,包含标题,作者等,后跟一个表,包含10列和任意数量的行。第一列是文本(通常是单个字符),第2,4和6列包含十进制数,其余列是非负整数。
我需要一个命令来查找包含的所有行,例如,第8列中的3
和第9列中的2
。该命令应返回此模式后面的行号列表。我怎样才能在bash脚本中执行此操作?我想将行号列表分配给变量(如lines=7 11
),以便我可以稍后在脚本中循环遍历其内容。
修改:按照@shelter的建议,我会发布完整的问题。
我需要查找包含的所有行,例如,第8列中的3
和第9列中的2
。然后我需要在所有这些行的第6列添加/减去一个固定数字,比如说3.4
。我怎么能这样做?
鉴于前面的示例输入文件,我希望得到以下输出文件:
示例输出
atomic structure.
created 8/4/15. author: becko
molecule name here
O 0.000000 0 0.000000 0 0.000000 0 0 0 0
C 1.422713 1 0.000000 0 0.000000 0 1 0 0
C 1.536633 1 109.666084 1 0.000000 0 2 1 0
C 1.523232 1 110.673515 1 57.147574 1 3 2 1
C 1.524902 1 110.675377 1 -51.051605 1 4 3 2
C 1.524624 1 110.815956 1 53.399712 1 5 4 3
O 1.388625 1 108.653427 1 -68.335587 1 2 3 4
O 1.418326 1 111.098351 1 61.526965 1 3 2 7
O 1.429752 1 106.981445 1 -172.599930 1 4 3 2
O 1.431727 1 110.929413 1 171.804962 1 5 4 3
C 1.389881 1 117.191086 1 95.674500 0 10 5 4
C 1.529863 1 107.679131 1 146.326675 0 11 10 5
C 1.524202 1 110.428741 1 170.992218 1 12 11 10
答案 0 :(得分:2)
简单的awk脚本:
awk '$8==3 && $9==2{print NR}'
每行会产生一个数字,但你仍然可以分配一个变量:
lines=$(awk '$8==3 && $9==2{print NR}' file.tsv)
或者,使用bash,作为数组:
lines=($(awk '$8==3 && $9==2{print NR}' file.tsv))
如果你真的希望所有数字都在一行上:
awk '$8==3 && $9==2{printf "%d ",NR}'
答案 1 :(得分:1)
假设col8
,col9
和add
是bash变量,分别包含要在第8列和第9列中匹配的值以及要添加到第6列的值, (例如col8=3 col9=2 add=3.4
)尝试:
awk '$8==a && $9==b{$6+=c}1' a=$col8 b=$col9 c=$add input-file
请注意,这会略微修改输出的间距。使输出均匀(但仍然不同于原始)的最简单方法可能是:
awk '$8==a && $9==b{$6+=c}{$1=$1}1' a=$col8 b=$col9 c=$add input-file
更重要的是,间距问题(您可以使用printf解决)是数据的精确度,因此您可能希望:
awk '$8==a && $9==b{$6+=c}1' CONVFMT=%0.9g a=$col8 b=$col9 c=$add input-file
这只是将shell变量col8,col9和add添加到awk变量a,b和c中,然后遍历文件的行。当列匹配时(规则$8==a && $9==b
的计算结果为true),将执行算术运算。 1
导致每行打印。