12

How to print using awk without a file.

script.sh
#!/bin/sh
for i in {2..10};do
awk '{printf("%.2f %.2f\n", '$i', '$i'*(log('$i'/('$i'-1))))}'
done

sh script.sh

Desired output
2   value
3   value
4   value
and so on

value indicates the quantity after computation

Kay
  • 1,957
  • 2
  • 24
  • 46

3 Answers3

16

BEGIN Block is needed if you are not providing any input to awk either by file or standard input. This block executes at the very start of awk execution even before the first file is opened.

awk 'BEGIN{printf.....

so it is like:

From man page:

Gawk executes AWK programs in the following order. First, all variable assignments specified via the -v option are performed. Next, gawk compiles the program into an internal form. Then, gawk executes the code in the BEGIN block(s) (if any), and then proceeds to read each file named in the ARGV array. If there are no files named on the command line, gawk reads the standard input.

awk structure:

 awk 'BEGIN{get initialization data from this block}{execute the logic}' optional_input_file
fedorqui
  • 275,237
  • 103
  • 548
  • 598
P....
  • 17,421
  • 2
  • 32
  • 52
  • 2
    This comes a little bit late but I think it's worth to mention: _An awk script does not wait for input if there isn't any pattern, default rule, or `getline` included to process the input._ I found this by accident and elaborated it a little bit in my [answer](https://stackoverflow.com/a/45158397/7478597) to a similar question on SO. – Scheff's Cat Jul 18 '17 at 07:06
  • @Scheff interesting information, it looks like gawk terminates immediately if there's only a `BEGIN` but will wait for input if there's only an `END`. – Masklinn Nov 09 '20 at 10:13
7

As PS. correctly pointed out, do use the BEGIN block to print stuff when you don't have a file to read from.

Furthermore, in your case you are looping in Bash and then calling awk on every loop. Instead, loop directly in awk:

$ awk 'BEGIN {for (i=2;i<=10;i++) print i, i*log(i/(i-1))}'
2 1.38629
3 1.2164
4 1.15073
5 1.11572
6 1.09393
7 1.07905
8 1.06825
9 1.06005
10 1.05361

Note I started the loop in 2 because otherwise i=1 would mean log(1/(1-1))=log(1/0)=log(inf).

fedorqui
  • 275,237
  • 103
  • 548
  • 598
6

I would suggest a different approach:

seq 2 10 | awk '{printf("%.2f %.2f\n", $1, $1*(log($1/($1-1))))}'
Michael Vehrs
  • 3,293
  • 11
  • 10