1

In a specific column, I need to replace rows with 'X', but only if they don't match any of 3 possible patterns (3 variables). Note that the column won't always be the same column, thus the code must work with the column number itself being a variable number. The same can be said for the 3 possible patterns. its difficult to explain without demonstration. in the example, if you look at column 1 and see how it changes specific ones to 'X' based on the 'GrabVariantOption's, then its probably clearer than anything I can explain.

Example input:

A,A,A,X
A,G,T,X
C,A,G,T
A,C,G,T
f,X,A,g
g,T,A,A
m,s,G,A
G,s,m,A

Example 3 possible patterns:

GrabVariantOption1=A
GrabVariantOption2=g
GrabVariantOption3=G

Some pseudo code, that is kind of the principle of what I want to do:

Column=1   

awk -F ',' -v a=$GrabVariantOption1 -v b=$GrabVariantOption2 -v c=$GrabVariantOption3 -v x=$Column '{$x; if NR!=a && NR!=b && NR!=c; flag=1} {if flag=1 NR==X }'

Example Output:

A,A,A,X
A,G,T,X
X,A,G,T
A,C,G,T
X,X,A,g
g,T,A,A
X,s,G,A
G,s,m,A
  • This question is not at all clear. Please explain in words how you need to transform the input into the output. – glenn jackman Aug 8 '19 at 12:55
  • Sorry, I've edited the question, to make it as clear as possible. – Giles Aug 8 '19 at 13:03
4
awk -F, -v OFS=, \
  -v "a=$GrabVariantOption1" \
  -v "b=$GrabVariantOption2" \
  -v "c=$GrabVariantOption3" \
  -v "x=$Column" '
  $x != a && $x != b && $x != c {$x = "X"}
  {print}'

Or here as those are single ASCII letters:

awk -F, -v OFS=, \
  -v "pattern=^[$GrabVariantOption1$GrabVariantOption2$GrabVariantOption3]\$" \
  -v "x=$Column" '
  $x !~ pattern {$x = "X"}
  {print}'

NR is a special variable in awk that holds the current record number (line number here with the default record separator). $ is an operator to dereference a field. So if x is the field number $ x gives you the content of the xth field.

| improve this answer | |
  • Brilliant!, that works great, and has also really helped improve my understanding of awk. – Giles Aug 8 '19 at 13:27
2

Another option:

awk -v col=1 -v keys="$GrabVariantOption1,$GrabVariantOption2,$GrabVariantOption3" '
    BEGIN {
        FS = OFS = ","

        # keys is a single string: "A,g,G"

        n = split(keys, a)

        # now, n=3 and a is the array ("A", "g", "G")

        for (i=1; i<=n; i++) keep[a[i]] = 1

        # now, keep is an associative array mapping "A"=>1, "g"=>1, "G"=>1
        # ("A" in keep) is true
        # ("C" in keep) is false
    }
    !($col in keep) {$col = "X"}
    {print}
' input
| improve this answer | |
1

Try this,

awk -F ',' -v a=$GrabVariantOption1 -v b=$GrabVariantOption2 -v c=$GrabVariantOption3 -v x=$Column -v OFS=',' '{if (($x != 'a') && ($x != 'b') && ($x != 'c')) {$x="X"}; print }' input.txt 
A,A,A,X
A,G,T,X
X,A,G,T
A,C,G,T
X,X,A,g
g,T,A,A
X,s,G,A
G,s,m,A
| improve this answer | |
0

Here is one way to look at the pbm using Gnu sed employing extended regexes:

$ col=1 opt1=G opt2=g opt3=G
$ opt=${opt1}${opt2}${opt3}
$ sed -Ee "
   s/^/,/
   s/(([^,]*,){$col})[^$opt]/\1X/
   s/,//
" file.csv

With Perl you could do like this also:

$ perl -lpe "
   s/^/,/;
   substr(\$_,2*$col-1,1) =~ tr/$opt/X/c;
   s/,//;
" file.csv
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.