awk - 循环中由条件分隔1列

时间:2014-09-17 11:39:34

标签: bash awk

亲爱的,我需要一些帮助。

我有这个输入文件:

 chr1
 chr1 
 chr2 
 chr2 
 chr3 
 chr3

我想将它分成以下输出文件:

"第一个文件"

chr1
chr1
chr1

"第二个文件"

chr2 
chr2

"第三个文件"

chr3
chr3

我正在使用此代码,但它无效

for i in {1..3}                 
do 
    awk '{if ($1 == "chr"$i) {print $0}}' 17_n.tsv > $i 
done

3 个答案:

答案 0 :(得分:1)

也许你可以使用这样的东西:

$ cat file
 chr1
 chr1
 chr2
 chr2
 chr3
 chr3
$ awk '{suffix = substr($1, length($1)); print > "file" suffix}' file
$ cat file1
 chr1
 chr1
$ cat file2
 chr2
 chr2
$ cat file3
 chr3
 chr3

基本上,取第一个字段的最后一个字符并用它来确定文件名。

如果最后可以有多个数字,您可以改用:

awk 'match($1, /[0-9]+$/) { print > ("file" substr($1, RSTART)) }' file

matchRSTART设置为匹配开头的位置,因此可以与substr一起使用以提取输入的数字部分。

答案 1 :(得分:1)

如果您的行格式为N non-number chars + N numbers,则可以尝试:

awk '{f=$0;sub(/^[^0-9]*/,"",f);print >("output"f)}' input

这对ch0r1无效。

如果您希望它也适用于ch0r1,请使用 gawk

awk '{f=gensub(/^.*[^0-9]([0-9]*)$/,"\\1","g");print >("output"f)}' file

答案 2 :(得分:1)

由于awk是一种与其自己的解释器不同的语言,bash变量无法在awk中正确使用而不首先使用-v选项传递它们。另外,awk中的默认操作是打印,因此您不需要{print $0}

所以这会奏效:

for i in {1..3}                 
do 
    awk -v i=$i '$1 == "chr"i' 17_n.tsv > $i 
done

也就是说,你也可以在read循环中完成你想要的东西:

while read -r line
do
    [[ $line == chr+([0-9]) ]] && echo $line >> ${line#chr}
done < 17_n.tsv