2017-08-02 79 views
0

我有一个文件,它看起来像这样一个筛选条件,两个文件

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一次并让它保存满足条件的行在一个文件中而那些不在另一个文件中的行?或者是其他东西?

编辑: 我忘了头在我的文件

回答

2

这是非常有可能在一个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 
+0

谢谢,我忘记了我的初始文件的标题。是否也可以将其保存到所有输出文件? – Hill

+1

是的。你可以添加(在开始处)'NR == 1 {print $ 0>“REMOVED_COL_3.txt”;打印$ 0>“REMOVED_COL_4.txt”;打印$ 0>“everythingelse_out.txt”}' – JNevill

+0

再一次,非常感谢这是完美的 – Hill

1
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#ConversionTo force a string to be converted to a number, add zero to that string.

+0

谢谢,我忘了我的初始文件的标题。是否也可以将其保存到所有输出文件? – Hill

+0

当然,我更新了答案。 –