替换小于1的字段,然后筛选值大于1的行

时间:2014-09-15 22:24:38

标签: csv awk sed

我一直在尝试过滤一些我长期拥有的csv文件。几乎是手工完成,因为我无法弄清楚为什么我的脚本不起作用。希望你们能弄清楚我做错了什么。

我有以下文件:csv file

我可以使用以下sed脚本替换小于1的值:

sed -e 's/[0][0-9]*\.[0-9]*/0/g'  genes.csv > genes-filtered1.csv

在下一步中,我想删除所有包含全零的行。但是,如果它们在至少一列中的值大于1,我想保留。我尝试了几个脚本,但它不起作用。

以下是其中一些:

awk '{ if ($2 > 1 || $3 > 1 || $4 > 1 || $5 > 1 || $6 > 1 || $7 > 1 || $8 > 1 || $9 > 1 || $10 > 1 || $11 > 1 || $12 > 1 || $13 > 1) print $0 }' genes-filtered1.csv > genes-filtered2.csv 

或者只是尝试使用阈值过滤一列:

threshold=1
awk -v threshold=$threshold '$3 > threshold' genes-filtered1.csv > genes-filtered2.csv

我也尝试过:

awk '{ for (i=2; i<=NF; i++) { if ($i != 0) { print; next } } }' genes-filtered1.csv > genes-filtered2.csv

最后我尝试了:

awk '{for (i=2;i<=NF;i++) if ($i>=1){print $0;next}}' genes-filtered1.csv > genes-filtered2.csv

问题是输出文件是空的还是与原始文件相同。任何建议如何解决它将不胜感激。还有可能有一个awk命令来执行我正在用sed做的事情,然后删除所有零的行? 谢谢

2 个答案:

答案 0 :(得分:2)

当您使用awk时,您并不需要使用sed。当任何一个字段大于f时,以下解决方案将启用标记1。如果该标志为真,那么我们将再次遍历字段并将所有小于1的值转换为0

awk '
BEGIN { FS = OFS = "," }         # Set input and output field separator to ,
{
    for (i=2; i<=NF; i++) 
        if ($i >= 1) { f = 1 }   # Enable a flag when any one field is greater than 1
}
f {
    for (i=2; i<=NF; i++) { 
        $i = ($i < 1 ? 0 : $i)   # If the flag is true convert values < 1 to 0
    }
    f = 0;                       # Set the flag to false
    print                        # Print the line
}' file

答案 1 :(得分:2)

awk '
BEGIN{ FS=OFS="," }
NR > 1 {
    allZeros = 1
    for (i=2; i<=NF; i++) {
        if ($i < 1) {
            $i = 0
        }
        else {
            allZeros = 0
        }
    }
}
!allZeros
' file