AWK在文件末尾打印NA的空行
我有一个老脚本,已经困扰了我一段时间了,其中有一个小错误,我还没有真正花时间去修复,但我认为是时候了。脚本基本上根据行的ID追加不同文件的列。例如 test1.txt:AWK在文件末尾打印NA的空行,awk,Awk,我有一个老脚本,已经困扰了我一段时间了,其中有一个小错误,我还没有真正花时间去修复,但我认为是时候了。脚本基本上根据行的ID追加不同文件的列。例如 test1.txt: a 3 b 2 test2.txt: a 5 b 9 。。。应产生以下结果: a 3 5 b 2 9 脚本本身如下所示: #!/bin/bash gawk 'BEGIN { OFS="\t" } { vals[$1,ARGIND]=$2; keys[$1] } END {
a 3
b 2
test2.txt:
a 5
b 9
。。。应产生以下结果:
a 3 5
b 2 9
脚本本身如下所示:
#!/bin/bash
gawk 'BEGIN { OFS="\t" }
{ vals[$1,ARGIND]=$2; keys[$1] }
END {
for (key in keys) {
printf "%s%s", key, OFS
for (colNr=1; colNr<=ARGIND; colNr++) {
printf "%s%s", vals[key,colNr], (colNr<ARGIND?OFS:ORS)
}
} printf "\n"
}' $1 $2
。。。i、 e.我在文件的最后与NA发生了一行。到目前为止,我只是手动删除了这一行,但最好不用这样做。我真的不知道这个奇怪的功能是从哪里来的,虽然。。。有人有什么想法吗?如果有必要的话,我正在OSX上使用GAWK
这里有一些实际的输入,这就是我试图使问题简单和中肯的结果=P
target_id length eff_length est_counts tpm
ENST00000574176 596 282 6 0.825408
ENST00000575242 103 718 105 5.19804
ENST00000573052 291 291 21 2.61356
ENST00000312051 223 192 2559 46.8843
我对target_id和tpm列感兴趣,其他的都不重要。我的完整脚本:
FILES=$(find . -name 'data.txt' | xargs)
# Get replicate names for column header
printf "%s" 'ENSTID'
for file in $FILES; do
file2="${file/.results\/data.txt/}"
file3="${file2/.\/*\//}"
printf "\t%s" $file3
done
printf "\n"
gawk 'BEGIN { OFS="\t" }
{ vals[$1,ARGIND]=$5; keys[$1] }
END {
for (key in keys) {
printf "%s%s", key, OFS
for (colNr=1; colNr<=ARGIND; colNr++) {
printf "%s%s", vals[key,colNr], (colNr<ARGIND?OFS:ORS)
}
} printf "\n"
}' $FILES
i、 e.所有文件都命名为data.txt,但位于不同名称的子文件夹中。更简单的惯用方法是
$ cat test1.txt
a 3
b 2
$ cat test2.txt
a 5
b 9
$ awk -v OFS="\t" 'NR==FNR{rec[$1]=$0;next}$1 in rec{print rec[$1],$2}' test1.txt test2.txt
a 3 5
b 2 9
对于实际输入
注:
-v OFS=\t用于输出中以制表符分隔的字段,传递文件的顺序对第一个解决方案很重要。
硬编码换行符,如中所示
printf "%-20s %-15s %-15s\n", rec1[$1],rec2[$1],$5
这不是一个好主意,因为它会降低脚本的可移植性。您可以用
printf "%-20s %-15s %-15s", rec1[$1],rec2[$1],$5;print # same effect
编辑:用于两个以上的文件
更简单的惯用方法是
$ cat test1.txt
a 3
b 2
$ cat test2.txt
a 5
b 9
$ awk -v OFS="\t" 'NR==FNR{rec[$1]=$0;next}$1 in rec{print rec[$1],$2}' test1.txt test2.txt
a 3 5
b 2 9
对于实际输入
注:
-v OFS=\t用于输出中以制表符分隔的字段,传递文件的顺序对第一个解决方案很重要。
硬编码换行符,如中所示
printf "%-20s %-15s %-15s\n", rec1[$1],rec2[$1],$5
这不是一个好主意,因为它会降低脚本的可移植性。您可以用
printf "%-20s %-15s %-15s", rec1[$1],rec2[$1],$5;print # same effect
编辑:用于两个以上的文件
就我所见,在输出的末尾出现一个空行的唯一原因是在脚本的末尾有一个printf\n,即使您刚刚打印了ORS,它也会添加一个新行,这也是我在OS X上使用gawk得到的 因为您的bash脚本本质上是一个awk脚本,所以我会用它制作一个合适的awk脚本。这还可以避免在shell脚本中错误地引用$1和$2会破坏外来文件名的问题。如果您最喜欢的文本编辑器理解Awk,这也会为您提供适当的语法高亮显示:
#!/usr/bin/gawk -f
BEGIN { OFS = "\t" }
{
vals[$1,ARGIND] = $2;
keys[$1] = 1;
}
END {
for (key in keys) {
printf("%s%s", key, OFS);
for (colNr = 1; colNr <= ARGIND; colNr++) {
printf("%s%s", vals[key,colNr], (colNr < ARGIND ? OFS : ORS));
}
}
}
对于更复杂的sed编辑脚本也可以这样做。据我所知,在输出末尾出现空行的唯一原因是在脚本末尾有一个printf\n,即使您刚刚打印了ORS,它也会添加一个新行 因为您的bash脚本本质上是一个awk脚本,所以我会用它制作一个合适的awk脚本。这还可以避免在shell脚本中错误地引用$1和$2会破坏外来文件名的问题。如果您最喜欢的文本编辑器理解Awk,这也会为您提供适当的语法高亮显示:
#!/usr/bin/gawk -f
BEGIN { OFS = "\t" }
{
vals[$1,ARGIND] = $2;
keys[$1] = 1;
}
END {
for (key in keys) {
printf("%s%s", key, OFS);
for (colNr = 1; colNr <= ARGIND; colNr++) {
printf("%s%s", vals[key,colNr], (colNr < ARGIND ? OFS : ORS));
}
}
}
更复杂的sed编辑脚本也可以这样做。NA字符串是否在实际输出中?使用…|尾部我只是在结尾处得到一个空行,如果我在文本编辑器/Excel/Textedit中查看文件,NAs就会出现。如果我删除结尾处的printf,我在那里什么也得不到。输出在两行之后停止。这可能是Excel读取空行的结果?哦,这似乎确实有效!谢谢^^将你上面的内容与我给你的脚本进行比较。看到区别了吗?由于某种原因,您在末尾添加了printf\n。顺便说一句,您使用find的方式很脆弱-您应该使用数组而不是变量来存储文件名。NA字符串是否在实际输出中?使用…|尾部我只是在结尾处得到一个空行,如果我在文本编辑器/Excel/Textedit中查看文件,NAs就会出现。如果我删除结尾处的printf,我在那里什么也得不到。输出在两行之后停止。这可能是Excel读取空行的结果?哦,这似乎确实有效!谢谢^^将你上面的内容与我给你的脚本进行比较。看到区别了吗?由于某种原因,您在末尾添加了printf\n。顺便说一句,您使用find的方式是脆弱的——您应该使用数组而不是变量来存储文件名++@sjsam是的,但我弄错了:-需要有-f,所以不能使用env。嗯,我必须用printf检查一下\n。。。但是,我使用bash的原因是,该脚本有一个稍大的脚本的一部分,该脚本可以在不同的子文件夹中找到任意数量的同名文件,因此我不能使其成为awk,只是我担心。@Sajber从bash中调用单独的awk脚本没有什么错。嗯,这甚至会使shell脚本更干净。与shebang的接触很好,这是一个经常被忽略的事实++@sjsam是的,但我弄错了:-需要有-f,所以不能使用env。嗯,我必须用printf检查一下\n。。。然而,我使用bash的原因是scri
pt有一个稍大一点的脚本的一部分,该脚本在不同的子文件夹中找到任意数量的同名文件,因此我恐怕只能将其设置为awk。@Sajber从bash中调用单独的awk脚本没有什么错。这甚至会使shell脚本更干净。对于示例文件来说效果很好,但我意识到它们可能太简单了。。。我只需要我的真实数据文件中的第一个ID和第五个值列,而你的版本似乎与之不符。@Sajber:介意在问题中发布一些实际的输入和输出吗;我只需要真实数据文件中的第一个ID和第五个值列,对于这两个文件?使用示例数据编辑原始问题所有文件看起来都一样,包含相同的ID第一列,但第五列的值不同。我还需要能够输入任意数量的这些文件,因为这取决于所讨论的实验。@Sajber:我已经为实际的输入文件提供了解决方案。如果足够的话,你可以接受答案。对于示例文件来说效果很好,但我意识到它们可能太简单了。。。我只需要我的真实数据文件中的第一个ID和第五个值列,而你的版本似乎与之不符。@Sajber:介意在问题中发布一些实际的输入和输出吗;我只需要真实数据文件中的第一个ID和第五个值列,对于这两个文件?使用示例数据编辑原始问题所有文件看起来都一样,包含相同的ID第一列,但第五列的值不同。我还需要能够输入任意数量的这些文件,因为这取决于所讨论的实验。@Sajber:我已经为实际的输入文件提供了解决方案。如果足够的话,你可以接受答案。