使用 awk 解析
Posted
技术标签:
【中文标题】使用 awk 解析【英文标题】:parsing using awk 【发布时间】:2012-12-24 12:12:33 【问题描述】:如何使用 awk 根据来自另一个文件的数据解析一个文件。
我做了一个脚本:
BEGIN FS="\t" ; OFS="\t"
while((getline<"headfpkm")>0)
++a
id[a]=$1
fpkm[a]=$2
print id[a],fpkm[a]
lastid=id[a]
print lastid
close("headfpkm")
/$lastid/
print $2,$3,$5,$7,$8,$14,fpkm[a]
a--
lastid=id[a]
END print "total lines=",FNR,"\n\nfile 1 index: ",a
当我运行它时:
/$ awk -f testawk.awk file2
它正确运行 BEGIN 部分,但没有给出任何输出。
NM_000014 5.04503
NM_000015 0.586677
NM_000016 1.138332278
NM_000017 0.64386
NM_000018 3.61746
NM_000019 2.8793
NM_000020 10.846
NM_000021 0.685098
NM_000022 46388.6
NM_000026 0.257471
NM_000026
total lines= 10
file 1 index: 10
搜索部分有什么问题吗?
文件 2 如下所示:
34 ACADM NM_000016 9606 hsa-miR-3148 3 80 87 0.003 -0.016 -0.094 0.082 0.112 -0.160 97
34 ACADM NM_000016 9606 hsa-miR-3163 1 623 629 0.001 -0.022 -0.020 0.065 0.125 -0.01 57
35 ACADS NM_000017 9606 hsa-miR-3921 3 68 75 0.013 0.192 -0.097 0.031 -0.039 -0.147 82
35 ACADS NM_000017 9606 hsa-miR-4303 2 67 73 0.012 0.150 -0.052 0.013 -0.039 -0.036 31
35 ACADS NM_000017 9606 hsa-miR-4653-5p 3 68 75 0.003 0.192 -0.097 0.031 -0.039 -0.157 84
37 ACADVL NM_000018 9606 hsa-miR-124 2 31 37 0.003 0.023 -0.057 0.012 -0.032 -0.171 76
37 ACADVL NM_000018 9606 hsa-miR-1827 2 135 141 -0.007 -0.043 -0.058 0.039 -0.069 -0.258 91
37 ACADVL NM_000018 9606 hsa-miR-2682 2 134 140 0.003 -0.014 -0.058 0.004 -0.047 -0.232 87
37 ACADVL NM_000018 9606 hsa-miR-449c 2 134 140 -0.035 -0.014 -0.058 0.004 -0.047 -0.270 92
37 ACADVL NM_000018 9606 hsa-miR-506 2 31 37 -0.016 0.023 -0.057 0.012 -0.032 -0.190 80
【问题讨论】:
+1 但是您能添加一些示例输入吗?在大多数情况下,getline()
的使用应该是avoided。如果没有它,可能有一种更简单、更安全的方法可以解决您的问题。
我需要从文件中读取一列。在这个测试用例中,我只使用前 10 行数据。文件很大。还是有一种方法可以使用 sed 打印文件并将每个流作为 awk 的输入?
我了解headfpkm
(以及您的while
循环)正在产生您所描述的输出。但是,如果您可以包含file2
的一些内容,将会很有帮助。您使用的方法几乎可以肯定不是这样做的方法。
【参考方案1】:
这将是一个猜测,因为我不能 100% 确定你想要完成什么。解决问题的更好方法是执行以下操作:
BEGIN
FS=OFS="\t"
FNR==NR
c++
a[$1]=$2
next
$3 in a
print $2,$3,$5,$7,$8,$14,a[$3]
END
printf "total lines=%s\n\nfile 1 index: %s\n", FNR, c
运行方式:
awk -f script.awk headfpkm file2
结果:
ACADM NM_000016 hsa-miR-3148 80 87 -0.160 1.138332278
ACADM NM_000016 hsa-miR-3163 623 629 -0.01 1.138332278
ACADS NM_000017 hsa-miR-3921 68 75 -0.147 0.64386
ACADS NM_000017 hsa-miR-4303 67 73 -0.036 0.64386
ACADS NM_000017 hsa-miR-4653-5p 68 75 -0.157 0.64386
ACADVL NM_000018 hsa-miR-124 31 37 -0.171 3.61746
ACADVL NM_000018 hsa-miR-1827 135 141 -0.258 3.61746
ACADVL NM_000018 hsa-miR-2682 134 140 -0.232 3.61746
ACADVL NM_000018 hsa-miR-449c 134 140 -0.270 3.61746
ACADVL NM_000018 hsa-miR-506 31 37 -0.190 3.61746
total lines=10
file 1 index: 10
【讨论】:
@bharat_iyengar:是的,你可以写,例如;if ($3 ~ /pattern/) ...
。请参阅我在上面所做的更新。这些是您正在寻找的结果吗?
是的,它有效。多谢。我想知道if x in y
语句是否与/$x/
相同
如果文件 1 很大并且我不想将它保存在数组中,那么是否可以同时运行两个流?例如sed '' file1 | awk -f script file2
我认为不会,而且我认为我从未尝试过。如果$x
是一个模式,那么它就是(例如); $0 ~ $x
。但通常你想测试一个变量是否等于另一个,例如:$0 == $x
.
管道 (|
) 符号用于将输出从一个命令传递到另一个命令。如果您希望加快处理大文件的速度,如果您有一台多核机器,我发现更好的方法是使用GNU parallel。例如,请参阅here。 HTH。以上是关于使用 awk 解析的主要内容,如果未能解决你的问题,请参考以下文章
使用 bash、sed、awk 解析像 .ini 这样的文件