0

I have a tab-separated file that looks as follows:

$ cat file
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011558474.1  1159543 1160595 -4330977        polyketide synthase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011558475.1  1160607 1161116 12      isoprenylcysteine carboxyl methyltransferase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011558476.1  1161113 1162129 -3      NAD(P)/FAD-dependent oxidoreductase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011559726.1  2496640 2497560 1334511 polyketide synthase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011559727.1  2497568 2498122 8       isoprenylcysteine carboxyl methyltransferase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011562574.1  5526997 5528142 3028875 NAD(P)/FAD-dependent oxidoreductase [Mycobacterium]

I need to pick up successive lines that contain the keywords 'polyketide synthase', 'methyltransferase', and 'oxidoreductase' in that order, and write each of these sets into separate files for further analysis.

In this case, the input file would yield 2 output files which would look as follows:

$ cat file_1
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011558474.1  1159543 1160595 -4330977        polyketide synthase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011558475.1  1160607 1161116 12      isoprenylcysteine carboxyl methyltransferase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011558476.1  1161113 1162129 -3      NAD(P)/FAD-dependent oxidoreductase [Mycobacterium]

$ cat file_2
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011559726.1  2496640 2497560 1334511 polyketide synthase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011559727.1  2497568 2498122 8       isoprenylcysteine carboxyl methyltransferase [Mycobacterium]
GCF_000015405.1_ASM1540v1.dist_nbr_anntn        WP_011562574.1  5526997 5528142 3028875 NAD(P)/FAD-dependent oxidoreductase [Mycobacterium]

I am having a hard time doing this using awk. Any suggestions?

P.S. I have other input files that contain variable number of instances of the keywords in successive lines. This is where I am getting stuck.

  • What make those two output files file_1 & file_2 different fro each other? what other files you are talking about other files that contain variable number of instances of the keywords in successive lines? please edit your question and make it a little more clear. – αғsнιη Apr 11 at 12:51
  • @αғsнιη Sorry if I was unclear in my question. file_1 and file_2 would contain different sets of the keyword instances in successive lines (you could look at the intended output files in the question for further clarification). Also, I have made the requested edit in the question. – BhushanDhamale Apr 12 at 5:40
1

You can change what you are searching for as the script progresses and change where you write to each time you cycle through your terms

awk 'BEGIN {
    result_file = 1;
    term_id = 1;
    search_terms[1] = "polyketide synthase";
    search_terms[2] = "methyltransferase";
    search_terms[3] = "oxidoreductase"
}
$0 ~ search_terms[term_id] { 
    print $0 >> FILENAME "_" result_file;
    term_id = term_id + 1;
    if (term_id > 3) {
        result_file =  result_file + 1;
        term_id = 1
    }
}' input_file

This will write to input_file_1, input_file_2...

1

You might test the following code, where I split your keywords into an awk array named keys with N elements. everything starts with keys[1] and we set up a flag to check the next 1 to N-1 lines if they matches the corresponding values in the array keys [index from 2 to N], any mismatches before the N-1 line will reset this flag, if it reaches the N-1 line, then all are good for output (we also reset flag=0 here so a consecutive run of flag==1 never exceeds N-1 lines):

$ cat t24.awk
BEGIN{ 
    FS = OFS = "\t";
    keywords = "polyketide synthase,methyltransferase,oxidoreductase";
    N = split(keywords, keys, ",")
}

# flag==1 means we are doing regex_match the next N-1 lines
# against corresponding array element in keys from [2:N] 
# once a unmatched found, turn off flag immediately
# if the flag==1 reached N-1 lines, then print the good match
flag {
    if($NF ~ keys[NR - start_line + 1]) {
        F = F ORS $0;
        if (NR == start_line+N-1) {print F > "out_" f++; flag = 0 }
        next
    } else {
        flag = 0;
    }
}

# set up the flag/start_line and reset F
$NF ~ keys[1] { flag = 1; F = $0; start_line= NR; }

Run the above code with awk -f t24.awk file.txt. You can set up keywords (comma delimited) from your shell(instead of hard-coded in the BEGIN block), and then use -v keywords="..." to make it more flexible.

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.