我有一个大文件,需要按第一个字段(从不重复)进行过滤。示例如下:
NC_056429.1_398 2 3 0.333333 0.333333 0.333333 0.941178
NC_056429.1_1199 2 0 0.333333 0.333333 0.333333 0.941178
NC_056442.1_7754500 0 3 0.800003 0.199997 0.000000 0.000001
NC_056442.1_7754657 1 2 0.000000 0.199997 0.800003 0.888891
NC_056442.1_7754711 2 0 0.888891 0.111109 0.000000 0.800002
NC_056442.1_7982565 0 1 0.800003 0.199997 0.000000 0.666580
NC_056442.1_7982610 1 0 0.800003 0.199997 0.000000 0.000000
NC_056442.1_7985311 2 0 0.888891 0.111109 0.000000 0.000000
我正在尝试使用 awk 按第一列过滤 shell 脚本中的文件,并且我需要使用变量,因为它在 while 循环中。 while 循环调用文本文件,例如:
NC_056442.1 7870000 # 1st field = $chrname, 2nd field = $pos
NC_056443.1 1570000
之前在脚本中,我使用 $pos 计算来找到目标值,以获得 $startpos 和 $endpos ,如下所示:
chrname="NC_056442.1" # column 1 in pulled file
startpos=7754657 # calculated in prior script
endpos=7982610 # calculated in prior script
start=${chrname}_${startpos} # this was an attempt to simplify the awk command
end=${chrname}_${endpos}
awk -v s="$start" -v e-"$end" '/s/,/e/' file.txt > cut_file.txt
如果我手动输入值(如下所示),我会得到一个仅包含第 5-8 行的文件。
awk '/NC_056442.1_7754657/,/NC_056442.1_7982610/' file.txt > cut_file.txt
输出文件
NC_056442.1_7754657 1 2 0.000000 0.199997 0.800003 0.888891
NC_056442.1_7754711 2 0 0.888891 0.111109 0.000000 0.800002
NC_056442.1_7982565 0 1 0.800003 0.199997 0.000000 0.666580
NC_056442.1_7982610 1 0 0.800003 0.199997 0.000000 0.000000
我很挣扎,因为我不知道如何让 s 和 e 变量实际运行。我尝试了多种选项,包括“ENVIRON[]”。作为 bash 的新手(也是这里的第一篇文章),我不知道如何解决这个问题。我愿意接受 awk 之外的答案。如果我需要重新表述我的问题或添加更多信息,请告诉我。
答案1
不要尝试通过匹配正则表达式来做到这一点。相反,使用_
或 space 作为 awk 的字段分隔符,这样您就可以在易于使用的变量中获得染色体和位置:
start=1234567
end=7654321
awk -v s="$start" -v e="$end" -F '[ _]' '$3 >= s && $3 <= e' file.txt > cut_file.txt
另外,避免在 shell 脚本中对变量名使用大写字母。按照惯例,全局环境变量都是大写的,因此如果您对自己的变量使用大写字母,可能会导致命名冲突并且很难发现错误。
现在,您还没有向我们展示您正在使用的循环。不管是什么,你最好在 awk 本身而不是 shell 中循环。 Shell 循环是慢的。