2

I'm using awk to create a file that contains lines of text & uses an input file of numbers. I want to substitute each number once, i.e. line 1 gets the first number, line 2 gets the second number, line 3 gets the third number. However, each line is assigned the first number, followed by each line assigned the second number, etc...

Here is my input file of text (test.awk):

{printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}"); 
}

this is the input file of numbers:

-0.00432739
0.41369093
0.00000000

command: awk -f test.awk < input.txt > new.txt

produces this where the 3 lines are repeated 3 times:

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1; h=0;}

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1; h=0;}

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

what I want is this:

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

Can anyone tell me how to stop it from assigning each number to each line and then repeating the 3 lines?

  • there's no need to redirect the input.txt into awk, just give it as parameter. – Oliver Friedrich Sep 6 '15 at 13:31
2

Using modulo 3 (%) and a little correction in printf(\"%%f %%s\n\",$1=="$1",$2)

{
  if (NR%3==1) {printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%3==2) {printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%3==0) {printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")}
}

Modulo is also a good idea, if you have more than three lines in your input.txt. The number 3 in the code above depends on the printf lines in test.awk. With four printf lines, you need something like this:

{
  if (NR%4==1) {printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%4==2) {printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}")};
  if (NR%4==3) {printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")};
  if (NR%4==0) {printf("\n($2 == \"foo.bar\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}")}
}

Output with three lines in input.txt:

% awk -f test.awk input.txt

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}

Output with more than three lines in input.txt

% awk -f test.awk input.txt

($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}
($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}
  • Don't thank me! ;-) If I could solve your problem, just click the little grey ☑ at the left-hand side of my answer, now turning it into beautiful green. If you like my answer, click on the little grey checkmark and the little up-arrow... – A.B. Sep 6 '15 at 17:04
1

You can use following awk code (test.awk):

BEGIN{count=0}{count++}{if(count==1){printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1;}");
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1;}");
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\n\",$1=="$1",$2); a=1; h=0;}"); }}
1

I would just save the numbers in an array and use that. First, modify your test.awk so that it looks like this:

($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;} 

You can do this automatically with this command:

sed -i 's/^{//;s/}$//;s/printf("\\n//;s/");//' test.awk 

Once that is done, you can use this script to get your output:

$ awk 'NR==FNR{a[NR]=$1; next}{gsub(/"\$1"/,a[FNR]); print}' input.txt test.awk 
($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1==-0.00432739,$2); a=1;} 
($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.41369093,$2); a=1;} 
($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.00000000,$2); a=1; h=0;} 

Explanation

NR is the current line number and FNR is the current line number of the current file. So, the two are equal only when the 1st file is being read. Therefore, the first part of the awk script above (NR==FNR{a[NR]=$1; next}) creates an array whose keys are the line numbers of the input.txt file and whose values are the corresponding numbers. It then runs next to move to the next line without executing the second part of the script.

The second part will substitute the string "$1" with the value stored in the array a for the current line number of the second file (FNR). The result is what you asked for.


Another approach would be to use some trickery. Instead of using a script for this, use paste to join the files and awk to make the substitution. First modify test.awk as described above, and then:

$ paste input.txt test.awk | awk '{gsub(/"\$1"/,$1);$1="";print;}'
 ($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1==-0.00432739,$2); a=1;}
 ($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.41369093,$2); a=1;}
 ($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1==0.00000000,$2); a=1; h=0;}

Explanation

The paste command will print each line of its input files together. So, with the input above, it will print:

$ paste input.txt test.awk
-0.00432739 ($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
0.41369093  ($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;} 
0.00000000  ($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;} 

This is then passed through an awk script which

  • Uses gsub to replace all occurrences of "$1" with the value of $1 (gsub(/"\$1"/,$1););
  • Once that is done, $1 is set to empty ($1="") so that the number from the first file is not printed at the beginning of the line.
  • Finally, it prints the resulting line (print).
0

Janet, you need to let awk know that after it applied the first line of code to the first input line, it ought to jump to the next input line. And then, that after it applied the second line of code, it ought to jump to the next input line and so on. Otherwise, awk applies each line of code on each input line. The easiest way to do so is to insert a getline command after each line of code (exept after the last one, where it is useless):

[alessandro@localhost ~]$ cat /tmp/a.awk
{printf("\n($2 == \"cs.cpool\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
getline
printf("\n($2 == \"cs.leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1;}"); 
getline
printf("\n($2 == \"cs.dead_leafc\") && (h==1) {printf(\"%%f %%s\\n\",$1=="$1",$2); a=1; h=0;}"); 
}
[alessandro@localhost ~]$ cat /tmp/a.txt
-0.00432739
0.41369093
0.00000000
[alessandro@localhost ~]$ awk -f /tmp/a.awk /tmp/a.txt
($2 == "cs.cpool") && (h==1) {printf("%f %s\n",$1==-0.00432739,$2); a=1;}
($2 == "cs.leafc") && (h==1) {printf("%f %s\n",$1==0.41369093,$2); a=1;}
($2 == "cs.dead_leafc") && (h==1) {printf("%f %s\n",$1==0.00000000,$2); a=1; h=0;}[alessandro@localhost ~]$ 

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.