2

I have a space-delimited file that looks like this:

0   22:16050847:T:C 0   16050847
0   rs62224609:16051249:T:C 0   16051249
0   22:16051250:G:A 0   16051250
0   GSA-rs138295790 0   16057310

How can I modify the second column so I extract only the first two parts? I would like my output to look like this:

0   22:16050847 0   16050847
0   rs62224609:16051249 0   16051249
0   22:16051250 0   16051250
0   GSA-rs138295790 0   16057310
2

Short awk approach:

awk '{split($2,a,":"); $2=(length(a)>1)? a[1]":"a[2] : $2}1' file

The output:

0 22:16050847 0 16050847
0 rs62224609:16051249 0 16051249
0 22:16051250 0 16051250
0 GSA-rs138295790 0 16057310

  • split($2,a,":") - split the 2nd field into array a by separator :
| improve this answer | |
1

If you have GNU awk:

gawk '{split($2,a,/[:-]/,c); $2 = sprintf("%s%c%s", a[1], c[1], a[2])} 1' file
0 22:16050847 0 16050847
0 rs62224609:16051249 0 16051249
0 22:16051250 0 16051250
0 GSA-rs138295790 0 16057310
| improve this answer | |
0

With perl:

perl -lpe 's/^\S+\s+[^:]+:[^:]+\K\S+//' file

With GNU sed:

sed -E ':t s/:\w+//2; tt' file

Output:

0   22:16050847 0   16050847
0   rs62224609:16051249 0   16051249
0   22:16051250 0   16051250
0   GSA-rs138295790 0   16057310
| improve this answer | |
0

This should do the trick, assuming your file is called my_file and you're using the bash shell. It should be easier to understand and apply to similar problems:

paste -d ' ' <(awk '{print $1}' my_file) \
  <(awk '{print $2}' my_file | sed 's/:.:.//' ) \
  <(awk '{print $3" "$4}' my_file)

So for each line of the inputs, paste merges the subsequent sections with a space delimiter, given by <().

  • The first awk section pulls out the first column entry
  • The second awk section takes the middle column and removes the second column, removing any :T:C like part
  • The third pulls out the remaining columns.

The result is:

0 22:16050847  0 16050847
0 rs62224609:16051249  0 16051249
0 22:16051250 0 16051250
0 GSA-rs138295790 0 16057310
| improve this answer | |
  • Assuming you have a shell with process substitution like e.g. bash. – phk May 25 '17 at 11:00
0

Bash:

while read -r f1 f2 rest; do
   printf '%s' "$f1" "$(expr " $f2" : '\([^:]*:[^:]*\).*' \| " $f2")" "$rest"; echo
   # the lone echo provides for the newline
done < yourfile

read will split the fields into $f1, $2, and all the remaining shall be clumped into the $rest. Then on the 2nd field, $f2, we run expr to extract the first and second colon-delimited fields. If this is not possible, then we end up using the $f2 variable itself.

Sed:

sed -e '
   s/[^[:space:]]\{1,\}/\
&\
/2
   :loop
      s/\n\(.*:.*\):.*\n/\n\1\n/
   tloop
   s/\n//g
' yourfile

We first envelop the 2nd field with \n and then run a loop around this region till there is just two fields (or, one field delimiter) left.

Perl:

perl -pe 's/\G[^:\h]+:[^:\h]+\K\S+//,next while /\S\h+\S/g' yourfile

perl -pe 's/^\h*\S+\h+(?:(?!:)\S)+:(?:(?!:)\S)+\K\S+//' yourfile

perl -F'(\h+)' -lane '
   /:/ and $_ = join ":", (/[^:]+/g)[0,1] for $F[/^\h/?4:2];
   print @F;
' yourfile

Result

0   22:16050847 0   16050847
0   rs62224609:16051249 0   16051249
0   22:16051250 0   16051250
0   GSA-rs138295790 0   16057310
| 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.