Kay
Kay

Reputation: 2077

How to make zero the entire row except the first column, if it has a zero in any other colum in Linux?

I would like to make zero the entire row except first column, if it has a zero value in any other column. e.g.,

ifile.txt
1   4.5   9
2   5.0   0
3   2.4   4
4   3.1   2
5   0.0   0
6   2.4   1
7   0.0   5

I am looking my output as

ofile.txt
1   4.5   9
2   0.0   0
3   2.4   4
4   3.1   2
5   0.0   0
6   2.4   1
7   0.0   0

Upvotes: 0

Views: 214

Answers (5)

henfiber
henfiber

Reputation: 1307

This achieves your desired outcome, while preserving white space:

gawk '!($2*$3) {$0 = gensub(/([[:space:].])[0-9]/,"\\10", "g")} 1' ifile.txt

Explanation:

  • Condition: !($2*$3) : If one of the 2nd or 3rd fields is zero (0) then their product will be zero
  • If the condition is true, replace all digits [0-9] which come after a space or dot [[:space:].] with zero (0)
  • \\10 : is actually \1 + 0 : meaning print the first match (the space or dot), followed by a literal zero (0)

If you want to make it work for an arbitrary number of fields, e.g. for the following input:

$ cat ifile_ext.txt
1   4.5   3.2   .5   1.9   2.0   9
2   5.0   6.4   .1   0.0   3.4   0
3   2.4   4.1   .4   2.3   1.0   4
4   3.1   2.0   .6   1.3   2.4   2
5   0.0   1.0   .9   2.3   0.0   0
6   2.4   2.0   .1   4.5   1.2   1
7   0.0   4.5   .2   9.4   0.0   5
8   1.0   2.0   .0   1.2   4.1   1

Then you have to loop over the fields, and then perform the same transformation:

gawk '{ for(i=2;i<=NF;i++) if (!$i) {$0 = gensub(/([[:space:].])[0-9]/,"\\10", "g")} } 1'  ifile_ext.txt

Output:

1   4.5   3.2   .5   1.9   2.0   9
2   0.0   0.0   .0   0.0   0.0   0
3   2.4   4.1   .4   2.3   1.0   4
4   3.1   2.0   .6   1.3   2.4   2
5   0.0   0.0   .0   0.0   0.0   0
6   2.4   2.0   .1   4.5   1.2   1
7   0.0   0.0   .0   0.0   0.0   0
8   0.0   0.0   .0   0.0   0.0   0

Upvotes: 1

NeronLeVelu
NeronLeVelu

Reputation: 10039

sed 's/$/ /;/[[:space:]]\(0\.\)\{0,1\}0[[:space:]]/!b o
s/\([^[:space:]]*\).*/\1 0.0 0/
:o
s/ $//' YourFile

with formating column

sed 's/$/ /;/[[:space:]]\(0\.\)\{0,1\}0[[:space:]]/!b o
h;s/[[:space:]].*//;x;s/[^[:space:]]*//;s/[1-9]/0/g;H;x;s/\n//
:o
s/ $//' YourFile

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204731

$ awk '!$2{$3=0} !$3{$2="0.0"} 1' file
1   4.5   9
2 0.0 0
3   2.4   4
4   3.1   2
5 0.0 0
6   2.4   1
7 0.0 0

Upvotes: 3

Andrzej Pronobis
Andrzej Pronobis

Reputation: 36146

Using bash (and bc) and for an arbitrary number of columns:

#!/bin/bash

IFS=$'\n'
for line in $(cat in.txt)
do
    found_zero=
    zeros=
    IFS=$' '
    # Find if zero in any column, and generate columns with zeros
    for e in ${line#* }
    do
        (( $(bc <<< "$e == 0.0") == 1 )) && found_zero=1
        zeros="$zeros 0.0"
    done
    # If found zero in a column, write only zeros
    if [ $found_zero ]
    then
        echo "${line%% *}$zeros"
    else
        echo $line
    fi
done

Upvotes: 1

lcd047
lcd047

Reputation: 5861

Assuming the columns in your input file are separated by tabs:

awk -F'\t' '{ if ($2 == 0 || $3 == 0) { $2 = 0; $3 = 0 }; printf("%d\t%.1f\t%d\n", $1, $2, $3) }' ifile.txt

Output:

1       4.5     9
2       0.0     0
3       2.4     4
4       3.1     2
5       0.0     0
6       2.4     1
7       0.0     0

Upvotes: 4

Related Questions