一个筛选条件,两个文件
我有一个文件,它看起来像这样一个筛选条件,两个文件
VAR1 VAR2 VAR3 VAR4
ID1 foo 0.1 0.1
ID2 foo 1 1
ID3 foo foo .
ID4 foo foo foo
ID5 foo . 1
ID6 foo -0.1 -0.1
ID7 foo -1 -1
ID8 foo 5e-08 5e-08
我想基于一个顺序的标准去筛选出列(如首先从第3列中删除所有非数字项,然后从第4列开始都是负数),但我想保存符合这些中间标准的所有行。也就是说,我的最终输出应该是1)一个文件,其中包含在第一步中删除的所有行,2)包含在下一步中删除的所有行的文件,以及3)包含过滤后存活的所有行的文件。
我走到这一步是:
awk '$3!=$3*1 {print}' <file.txt> REMOVED_COL_3.txt
if [[ $(find REMOVED_COL_3.txt -type f -size +0c 2>/dev/null) ]]
then
awk '$3==$3*1' <file.txt> tmp.txt && mv tmp.txt file.txt
fi
awk '$4<0 {print}' <file.txt> REMOVED_COL_4.txt
if [[ $(find REMOVED_COL_4.txt -type f -size +0c 2>/dev/null) ]]
then
awk '$4>=0 {print}' <file.txt> tmp.txt && mv tmp.txt file.txt
fi
其中一期工程,但需要花费大量的时间在我的真实数据集(-13万行预过滤)。
是否可以将awk
一次并让它保存满足条件的行在一个文件中而那些不在另一个文件中的行?或者是其他东西?
编辑: 我忘了头在我的文件
这是非常有可能在一个awk脚本。您可以在awk
使用if/else if/else
以及重定向您的个人print
声明不同的文件:
awk '{ if ($3!=$3*1) {print $0 > "REMOVED_COL_3.txt"} else if ($4<0) {print $0 > "REMOVED_COL_4.txt"} else {print $0 > "everythingelse_out.txt"}}' file.txt && mv -f everythingelse_out.txt file.txt
awk '
NR==1 {
split("REMOVED_COL_3.txt REMOVED_COL_4.txt tmp.txt",outfiles)
for (outnr in outfiles) {
print > outfiles[outnr]
}
next
}
{
if ($3 != $3+0) { outnr=1 }
else if ($4 < 0) { outnr=2 }
else { outnr=3 }
print > outfiles[outnr]
}
' file.txt &&
mv tmp.txt file.txt
我用的$3+0
代替$3*1
将字符串转换为数字,因为除了通常比乘法运算快一点这是执行该操作的更常见的方式,请参阅https://www.gnu.org/software/gawk/manual/gawk.html#Conversion:To force a string to be converted to a number, add zero to that string.
谢谢,我忘了我的初始文件的标题。是否也可以将其保存到所有输出文件? – Hill
当然,我更新了答案。 –
谢谢,我忘记了我的初始文件的标题。是否也可以将其保存到所有输出文件? – Hill
是的。你可以添加(在开始处)'NR == 1 {print $ 0>“REMOVED_COL_3.txt”;打印$ 0>“REMOVED_COL_4.txt”;打印$ 0>“everythingelse_out.txt”}' – JNevill
再一次,非常感谢这是完美的 – Hill