1

I want to convert this file in Linux...

1:a:A:G rs123
1:b:C:T rs456
1:c:G:A,C rs174

To this file...

1:a rs123
1:b rs456
1:c rs174

Would anybody know how to do this? Thank you in advance!

2
  • 1
    can someone please tell why he upvoted this? this does not show any effort of the OP what so ever
    – der bender
    Commented Apr 24, 2020 at 19:18
  • If that’s all you want, you can get it with printf '%s\n' '1:a rs123' '1:b rs456' '1:c rs174'. If you want a solution that can handle different input, you should describe all the variations that can appear. For example, could you have 1:a:a:G, 1:A:A:G, 1:a:A or 1:c:G:A:C? Commented Aug 24, 2020 at 20:24

4 Answers 4

5

If all input values are consistent , then just print all columns except those two :

awk -F'[: ]' '{ print $1":"$2"  "$5 }' inputFile
4

Nothing wrong with @terdon solution but just for fun a gawk solution using

awk -F':[^a-z]+' '{print $1, $2}' file1

Composes IFS as a contextual regex which matches any contiguous string starting : followed by a variable length combination of anything except lower case letters [^a-z]+, which just leaves you with the two chunks you want.

2
  • Ha! I had never considered that we could use a negated character class in the FS, nice!
    – terdon
    Commented Apr 24, 2020 at 16:46
  • @terdon It's your fault for grabbing the low hanging fruit. Had to find something creative!
    – bu5hman
    Commented Apr 24, 2020 at 16:49
4

A few choices:

$ awk -F'[: ]' '{print $1":"$2,$5}' file 
1:a rs123
1:b rs456
1:c rs174

This tells awk to use either a space or a : as the field separator and then to print the first field, a :, the second field and the 5th field.

$ sed -E 's/^([^:]*:[^:]*):.* (.*)$/\1 \2/' file 
1:a rs123
1:b rs456
1:c rs174

Here, sed captures any non-: ([^:]*) from the beginning of the line (^) until the first : and the next stretch of non-: characters until the second :. Then, we match everything until the final space of the line and capture any characters after it. Finally, the whole line is replaced by the two captured patterns (\1 \2).

$ perl -pe 's/(.+?:.+?):.*\s(\S+)$/$1 $2/' file 
1:a rs123
1:b rs456
1:c rs174

This is the same basic idea as the sed approach above but uses non-greedy regex patterns and searches for non-whitespace characters after the last whitespace character on the line.

2

Apart from all the GNU coreutil solutions it would also work if you open it in vim and type

:%norm 0f:f:vf hd

followed by Enter.

What it does:

: gets you in command mode

% modifier to have norm run on all lines in the file

norm a command that can run on multiple lines and just does as if you typed what ever it is followed by in normal mode.

0 to get to the beginning of the line

f: to go to the next occurence of the colon symbol in the text (i.e. your field seperator. Do this twice to get to the beginning of the 3rd column

v to enter visual mode (because that makes selecting the stuff to delete a whole lot easier :-) )

(note the space!!) to go to the next occurence of the space (i.e. the other field seperator) h to go one character to the left (so that we do not delete the space when we do delete our selection afterwards) and finally

d to delete the selected stuff

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .