print specific value from 7th column using pattern matching along with first 6 columns

Viewed 93

file1

1 123 ab456 A G PASS AC=0.15;FB=1.5;BV=45; 0|0  0|0  0|1  0|0  
4 789 ab123 C T PASS FB=90;AC=2.15;BV=12; 0|1 0|1 0|0 0|0  

desired output

1 123 ab456 A G PASS AC=0.15  
4 789 ab123 C T PASS AC=2.15  

I used

awk '{print $1,$2,$3,$4,$5,$6,$7}' file1 > out1.txt
sed -i 's/;/\t/g' out1.txt
awk '{print $1,$2,$3,$4,$5,$6,$7,$8}' out1.txt

output generated

1 123 ab456 A G PASS AC=0.15  
4 789 ab123 C T PASS FB=90  

I want to print first 6 columns along with value of AC=(*) from 7th column.

5 Answers
$ awk '{
    n=split($7,a,/;/)                 # split $7 on ;s
    for(i=1;i<=n&&a[i]!~/^AC=/;i++);  # just loop looking for AC
    print $1,$2,$3,$4,$5,$6,a[i]      # output
}' file

Output:

1 123 ab456 A G PASS AC=0.15
4 789 ab123 C T PASS AC=2.15

If AC= was not found, and empty field is outputed instead.

With your shown samples, please try following awk code.

awk '
{
  val=""
  while(match($7,/AC=[^;]*/)){
    val=(val?val:"")substr($7,RSTART,RLENGTH)
    $7=substr($7,RSTART+RLENGTH)
  }
  print $1,$2,$3,$4,$5,$6,val
}
'  Input_file

Explanation: Adding detailed explanation for above.

awk '                             ##Starting awk program from here.
{
  val=""                          ##Nullifying val here.
  while(match($7,/AC=[^;]*/)){    ##Running while loop to use match function to match AC= till semi colon all occurrences here.
    val=(val?val:"")substr($7,RSTART,RLENGTH)  ##Creating val and keep adding matched regex value to it, from 7th column.
    $7=substr($7,RSTART+RLENGTH)  ##Assigning rest pending values to 7th column itself.
  }
  print $1,$2,$3,$4,$5,$6,val     ##Printing appropriate columns required by OP along with val here.
}
' Input_file                      ##Mentioning Input_file name here.

Any time you have tag=value pairs in your data I find it best to first populate an array (f[] below) to hold those tag-value mappings so you can print/test/rearrange those values by their tags (names).

Using any awk in any shell on every Unix box:

$ cat tst.awk
{
    split($7,tmp,/[=;]/)
    for (i=1; i<NF; i+=2) {
        f[tmp[i]] = tmp[i] "=" tmp[i+1]
    }
    sub(/[[:space:]]*[^[:space:]]+;.*/,"")
    print $0, f["AC"]
}

$ awk -f tst.awk file
1 123 ab456 A G PASS AC=0.15
4 789 ab123 C T PASS AC=2.15

This might work for you (GNU sed):

sed -nE 's/^((\S+\s){6})\S*;?(AC=[^;]*);.*/\1\3/p' file

Turn off implicit printing -n and add easier regexp -E.

Match the first six fields and their delimiters and append the AC tag and its value from the next.

With only GNU sed:

$ sed -r 's/(\S+;)?(AC=[^;]*).*/\2/' file1
1 123 ab456 A G PASS AC=0.15
4 789 ab123 C T PASS AC=2.15

Lines without a AC=... part in the 7th field will be printed without modification. If you prefer removing the 7th field and the end of the line, use:

$ sed -r 's/(\S+;)?(AC=[^;]*).*/\2/;t;s/\S+;.*//' file1
Related