include library of functions in awk

2020-06-18 03:29发布

There are many common functions (especially arithmetic/mathematics) that are not built into awk that I need to write myself all the time.

For example:

  1. There is no c=min(a,b) , so in awk i constantly write c=a<b?a:b
  2. same for maximum i.e. c=max(a,b)
  3. same for absolute value i.e. c=abs(a) so i have to constantly write c=a>0?a:-a
  4. and so on....

Ideally, I could write these functions into an awk source file, and "include" it into all of my instances of awk, so I can call them at will.

I looked into the "@include" functionality of GNU's gawk , but it just executes whatever is in the included script - i.e. I cannot call functions.

I was hoping to write some functions in e.g. mylib.awk, and then "include" this whenever I call awk.

I tried the -f mylib.awk option to awk, but the script is executed - the functions therein are not callable.

标签: awk
5条回答
Root(大扎)
2楼-- · 2020-06-18 04:16

With GNU awk you can use the -i command line option or from inside a script the @include directive, but if you want a POSIX solution then awk -f functions.awk -f script.awk file.txt is the way you need to go.

查看更多
ゆ 、 Hurt°
3楼-- · 2020-06-18 04:17

on regular awk (non gnu) you can still fake a bit using the shell using a cat of the file(s) into the 'code' (generally in front, but could be everywhere since it respect the awk way of working order)

> cat /tmp/delme.awk
   function PrintIt( a) { printf( "#%s\n", a )}

> echo "aze\nqsd" | awk "$( cat /tmp/delme.awk)"'{ sub( /./, ""); PrintIt( $0 )}'
#ze
#sd
查看更多
走好不送
4楼-- · 2020-06-18 04:24

In case if you can't use -i (if your awk < 4.1 version ), which EdMorton suggested, make a try of below works with GNU Awk 3.1.7

--source program-text

Provide program source code in the program-text. This option allows you to mix source code in files with source code that you enter on the command line. This is particularly useful when you have library functions that you want to use from your command-line programs

$ awk --version
GNU Awk 3.1.7
Copyright (C) 1989, 1991-2009 Free Software Foundation.

$ cat primes.awk 
function abs(num) { return (num > 0 ? num : -num) }
function max(a,b) { return (a > b ? a : b) }
function min(a,b) { return (a < b ? a : b) }

$ awk -f primes.awk --source 'BEGIN{print min(4,7), abs(-3)}'
4 3
查看更多
混吃等死
5楼-- · 2020-06-18 04:32

With GNU awk:

$ ls lib
prims.awk

$ cat lib/prims.awk
function abs(num) { return (num > 0 ? num : -num) }
function max(a,b) { return (a > b ? a : b) }
function min(a,b) { return (a < b ? a : b) }

$ export AWKPATH="$PWD/lib"

$ awk -i prims.awk 'BEGIN{print min(4,7), abs(-3)}'
4 3

$ cat tst.awk
@include "prims.awk"
BEGIN { print min(4,7), abs(-3) }

$ awk -f tst.awk
4 3
查看更多
放荡不羁爱自由
6楼-- · 2020-06-18 04:36

You can have multiple -f program-file options, so one can be your common functions and the other can be a specific problem solving awk script, which will have access to those functions.

awk -f common-funcs.awk -f specific.awk file-to-process.txt

I don't know if this is what you were looking for, but it's the best I've come up with. Here's an example:

$ cat common_func.awk
# Remove spaces from front and back of string
function trim(s) {
  gsub(/^[ \t]+/, "", s);
  gsub(/[ \t]+$/, "", s);
  return s;
}

$ cat specific.awk
{ print $1, $2 }
{ print trim($1), trim($2) }

$ cat file-to-process.txt 
abc    |    def   |

2$ awk -F\| -f common_func.awk -f specific.awk file-to-process.txt 
abc         def   
abc def

With regular awk (non-gnu) you can't mix the -f program-file option with an inline program. That is, the following won't work:

awk -f common_func.awk '{ print trim($1) }' file-to-process.txt # WRONG 

As pointed out in the comments, however, with gawk you can use the -f option together with -e:

awk -f file.awk -e '{stuff}' file.txt
查看更多
登录 后发表回答