在bash脚本中使用awk提取模式

时间:2015-09-29 04:15:11

标签: bash shell awk

我有这个制表符分隔文件。

Test.txt的

chr1      10111412      apples
chr2      195121230     pears
chr2      991924122     elephants

如果我想要chr2中第1列的内容,

awk '/chr2\t/ Test.txt

输出:

chr2      195121230     pears
chr2      991924122     elephants

但是如果我从chr1到chr25有几亿行,并且需要将它们分成特定于chr的文本文件,我想到这样做:

#!/bin/sh
for num in $(seq 1 25)
do
awk '/chr$num\t/' Test.txt > chr$num.txt
done

我也尝试将awk更改为sed

sed -n 'chr$num\t/p' Test.txt

当然两者都失败了。我怀疑脚本将'/chr$num\t/'识别为单个变量。如何打破这种识别模式并让脚本运行?

3 个答案:

答案 0 :(得分:5)

您可以调整此代码:

awk '$1 ~ /^chr[0-9]+$/ { x = $1; gsub(/chr/, "file.", x); print > x }'

给定输入流:

chr1 d e
chr1 f g
chr44 abc def
chr3 cba fed

它会生成3个文件,file.1file.3file.44。您可以通过弄乱gsub()函数调用来轻松控制生成的文件名。

请注意,这会使数据文件单次传递,这比通过大量文件传递25次更为明智。

使用awk的GNU和Mac OS X(BSD)版本进行测试。

答案 1 :(得分:3)

使用awk

可以更简单地完成
awk '{print >> $1".txt"}' input.file

那就是它。

如果文件非常大并且您拥有大量第一列的不同值,则可能会用完文件描述符。在这种情况下,您需要在写入文件后关闭该文件:

awk '{f=$1".txt"; print >> f; close(f)}' input.file

答案 2 :(得分:1)

您需要"而不是'

单引号不会插入任何内容,但会引用双引号(例如变量,反引号,某些\转义等等)。

尝试以下脚本。

#!/bin/sh
for num in $(seq 1 25)
do
awk "/chr$num\t/" Test.txt > chr$num.txt
done