0

I have a tab-separated file that looks like:

$ cat file
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558474.1  1155234 1156286 polyketide      synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558475.1  1156298 1156807 12      carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558476.1  1156804 1157820 -3      oxidoreductase [Mycobacterium]

where 1155234, 1156286, 1156298, 1156807, 1156804 and 1157820 are followed by tabs (i.e., there are no spaces in the file except in the 6th (last) column).  I want to add 0 and a tab at the fifth column, and replace the tab at the end of the 6th column on the first line with a space. The output would look as follows:

GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558474.1  1155234 1156286 0       polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558475.1  1156298 1156807 12      carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558476.1  1156804 1157820 -3      oxidoreductase [Mycobacterium]

How do I do it using awk or sed?

  • Your question is confusing, because (1) Since 1155234, 1156286, 1156298, 1156807, 1156804 and 1157820 are all seven digits long, we can’t tell by looking at your example whether they are followed by spaces or tabs.   (2)  “Add (something) at the fifth column” is unusual terminology.   It would be more common to say “add (something) before the fifth column” or “insert a new column containing (something) before the fifth column” (or “after the fourth column”).  … (Cont’d) – G-Man Apr 20 at 8:17
  • (Cont’d) …  (3) Even assuming that the seven-digit numbers are followed by tabs, I see only six columns, so “the tab at the end of 6th column” doesn’t make much sense.   (4) OK, after looking at this for ten minutes, I figured out that, after you insert a new field, you have seven fields.   (5) Your example output shows that you want both changes to occur on only the first line, but that’s not clear from your description of what you want. – G-Man Apr 20 at 8:17
1

Your answer may do essentially what you want, but it can be improved.

  • You want to minimize the number of (simple) commands and the number of pipes, within reason.  Having more of them than you need can be inefficient.  You won’t notice it on a file of five or ten lines, but, when you process a file with a million lines, it can make a difference.

    You don’t need to run two sed commands (one piped into the other).  You can do

    sed -e '(firstscommand)' -e '(secondscommand)'
    or
    sed '(firstscommand); (secondscommand)'

  • It appears from your example output that you want that tab turned into the space on only the first line, so your s/\t/ / command should also be prefixed 1.
  • The behavior of s/…/…/6g is not defined.  Since you want the s/\t/ / to be done only once (on the 6th tab), you should say just s/\t/ /6 (without the g).

So your command could be

sed '1s/\t/\t0\t/4; 1s/\t/ /6' file

Braces let you group commands that you want done together.  So you could also say

sed '1{s/\t/\t0\t/4; s/\t/ /6}' file

awk

You can do this in awk as follows:

awk -F '\t' -v OFS='\t' 'NR==1 { $6 = $5 " " $6; $5 = "0" }
                { print }
    ' file

2

It seems as if you have six tab-delimited columns, but that some processing has left the first word of the 6th column in the 5th column when the value in the 5th column is missing. This is probably due to a previous processing step using spaces or general whitespace as delimiters rather than a tab.

Now you want to insert a zero into the 5th column and move the word there to its rightful place in the 6th column.

I'm going to assume that the file looks like the following, where each ^I is a tab character (this is the output of cat -t on the file):

GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558474.1^I1155234^I1156286^Ipolyketide^Isynthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558475.1^I1156298^I1156807^I12^Icarboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn^IWP_011558476.1^I1156804^I1157820^I-3^Ioxidoreductase [Mycobacterium]

It's unclear whether there's an empty column 2. If there is, just add one to the column numbers I use below.

$ awk -F '\t' 'BEGIN { OFS=FS } $5 ~ /[[:alpha:]]/ { $6 = $5 " " $6; $5 = 0 } { print }' file
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558474.1  1155234 1156286 0       polyketide synthase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558475.1  1156298 1156807 12      carboxyl methyltransferase [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn        WP_011558476.1  1156804 1157820 -3      oxidoreductase [Mycobacterium]

Here, I use awk to detect any alphabetical letter in the 5th column. If there is one, the 5th column is prepended with a delimiting space to the 6th column, and the 5th column is set to zero. All lines, modified or not, are then outputted.

  • Great minds think alike.  (The action part of your answer is identical to mine, except you left off the unnecessary quotes.) – G-Man Apr 20 at 20:26
  • @G-Man Ah, yes, I didn't even see your awk variant, sorry. I went for a generic solution that assumed that any line could be found to be corrupted in this way. – Kusalananda Apr 20 at 20:52
0

You can slice and dice arrays with the splice builtin in your scenario as shown:

$ perl -F\\t -pale '
  next unless $. == 1;
  splice @F, 4, 2, 0, join $", @F[-2,-1];
  $_ = join "\t", @F;
' input.file
0

Use sed -e '1s/\t/\t0\t/4' -e 's/\t/ /6g' file

The first sed command will substitute the first occurrence of <tab> with <tab>0<tab> on 4th column of first line. The second sed command will substitute all <tab> with <space> in the 6th column.

-1

Tried with below command its worked fine

awk 'NR==1 {$8=$7;$7=$6;$6=$5;$5=0}1' filename| sed -r "s/\s+/ /g"| sed "s/ /\t/g"

output

GCF_000014165.1_ASM1416v1.dist_nbr_anntn    WP_011558474.1  1155234 1156286 0   polyketide  synthase    [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn    WP_011558475.1  1156298 1156807 12  carboxyl    methyltransferase   [Mycobacterium]
GCF_000014165.1_ASM1416v1.dist_nbr_anntn    WP_011558476.1  1156804 1157820 -3  oxidoreductase  [Mycobacterium]

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.