1

I have an input file thus:

3.59717487E+05  3.40210880E+06        4075.32   7066.00   4075.32 7066      4075.322 2 a_final_psdm_LY1-1250_20160307             
3.59725248E+05  3.40211860E+06        4063.53   7067.00   4063.53 7067      4063.527 2 a_final_psdm_LY1-1250_20160307             
3.59733009E+05  3.40212840E+06        4051.73   7068.00   4051.73 7068      4051.731 2 a_final_psdm_LY1-1250_20160307             
3.59740771E+05  3.40213820E+06        4039.94   7069.00   4039.94 7069      4039.936 2 a_final_psdm_LY1-1250_20160307   

I need to get the last column and define a variable that is just the LY1-1250 part. This is what I have so far:

awk ' 
BEGIN{

     if($NF !~ /LY1/){
       print
     }
     else{

        tag=$NF
        print tag
     }
 }

but this gives me tag=a_final_psdm_LY1-1250_20160307

I need tag=LY1-1250

In a shell script I would just do

tag=`echo $NF | sed ... blah blah

but within awk it doesn't seem to evaluate the expression.

1

Since the "tag" is the part after the penultimate _, you can simply use that as a field separator:

$ awk -F_ '{if($(NF-1)~/LY1/){print $(NF-1)}else{print}}' file
LY1-1250
LY1-1250
LY1-1250
LY1-1250

Or, to use it as a variable:

awk -F_ '{if($(NF-1)~/LY1/){tag=$(NF-1); print tag}else{print}}' file

I don't understand why you had your code in a BEGIN{} block, that would only have been run once and before any lines were read, so NF wouldn't even be defined.

Anyway, for the general case, the way to save a substring in a variable in awk is to use substr or sub. So, you could also have done something like:

$ awk '{ 
        if($NF~/LY1/){
            tag=$NF; 
            sub(/.*LY1/,"LY1",tag); 
            sub(/_[^_]*$/,"",tag); 
            print tag
        }
        else{ print } }' file
LY1-1250
LY1-1250
LY1-1250
LY1-1250
  • Clever trick, but may I ask why you put the conditions inside the code block, rather than in from of it? – Bex Apr 21 '16 at 12:54
1

I think you may have misunderstood the conditionals of awk. The beginning of each line is the condition. This is a more... awk-ward way to do it: What about

awk '
/LY1/ { 
        tag=gensub(/_.*/,"","1",gensub(/.*LY1/,"LY1","1", $NF))
        print tag
        next
}
{
    print
}' input.file

The first /LY1/ is an implicit matches-condition - it only executes the expression if the input line matches that regular expression. The expression starts with substituting everything on that line, up to, and including, LY1 with LY1, and puts that in variable tag. It then prints tag, and the next-statement skips all other expressions for this record.

After that comes an unconditional expression, that just prints the line as it is - but this won't be executed if the prior expression was executed, since that would have called next.

  • This is almost exactly what I want except that it prints the characters after the section i want as well. i.e. LY1-1250_20160307. Can I limit the number of characters it prints? – jaffa1201 Apr 21 '16 at 11:45
  • Sure, updated the answer to fix that. May I ask what awk you are using? gawk, nawk, or something else? – Bex Apr 21 '16 at 12:45
1

Give a try to this:

awk '
{
   if(!match($NF,"LY1[^_]*")){
     print
   }
   else {
     tag=substr($NF,RSTART,RLENGTH)
     print tag
   }
}' input.file

match() finds the regular expression.

This function is also setting two special variables RSTARTand RLENGTH that indicate where the regular expression begins and ends.

  • Thanks for your answer. I really need to have the value defined as a variable as it will be used further down the script. – jaffa1201 Apr 21 '16 at 10:20
  • @jaffa1201 the tag variable had been added, see the updated answer. – Jay jargot Apr 21 '16 at 10:23
  • That works perfectly! Is it possible to have it take 8 characters starting from the letter L, rather than defining the starting character? the string may be defferent lengths elsewhere in the file (this is why i wanted to use sed). Thanks mate. – jaffa1201 Apr 21 '16 at 10:29
  • @jaffa1201 the RLENGTH had been replaced with 8 in the answer. I understand it should met your last requirement – Jay jargot Apr 21 '16 at 11:25
  • it is the RSTART that i would like to change to match a string; say LY1. – jaffa1201 Apr 21 '16 at 12:00

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.