linux awk与shell 参数互传

 

awk与shell间参数(或说变量传递)是shell编程中常有的话题了,因为其中实际涉及到不少的知识点,比如包括

a:进程进通信

b:awk参数形式

c:shell命令解析,命令替换

等等,在此列举二三点例子,做为小结。以下主要分为二部分

1:shell给awk传参

2:awk往shell传参

参考文档:gnu 的awk documentation

http://www.gnu.org/software/gawk/manual/gawk.html#Language-History

===================================

第一部分,shell往awk传参

 

 

首先得理解下awk的二种变量,和三种参数(变量)附值形式

 

二种变量,这里指内部变量,和自定义变量(本文先不讨论awk的函数局部变量,后续有空补上)

和shell一样,awk也有一些内置的变量,如NR,NF等,变量的赋值了有各自的规则(不再展开,具体看awk文档各变量说明)

自定义变量,通常是为程序需要自身定义的变量,不具有像内置变量那样的作用。

这二类变量的附值,实际上并没多少差别,只是文档中有提到,对内置变量的附值,有可能会得到不期望的结果,有些是被接收的,有些是不被接受的(原文:Caution: Using -v to set the values of the built-in variables may lead to surprising results. awk will reset the values of those variables as it needs to, possibly ignoring any predefined value you may have given.)

 

awk三种变量赋值形式:

1:-v var=text

     特点,一次一附值一次,作用在BEGIN模块之前,命令行位置必需要文件类参数之前,可以更改内置变量,不收录ARGV

      常用于传shell变量给awk

2:BEGIN模块

      特点:awk程序体进行的变量附值 ,其中BEGIN模块的执行在读输入之前,可以更改内置变量

      典型的用法是在没输入的时候运行一段awk程序就写在begin里

 

3:无-v的var=text形式

      特点:可以更改内置变量,类同文件类参数,收录进ARGV,放在文件类参数前,在文件类参数对应文件开始读入前起作用

 PS:

1、获得普通外部变量

[chengmo@localhost ~]$ test='awk code'                           
[chengmo@localhost ~]$ echo | awk  '{print test}' test="$test"
awk code
[chengmo@localhost ~]$ echo | awk  test="$test" '{print test}'
awk: cmd. line:1: fatal: cannot open file `{print test}' for reading (No such file or directory)

 

格式如:awk ‘{action}’  变量名=变量值   ,这样传入变量,可以在action中获得值。 注意:变量名与值放到’{action}’后面。

[chengmo@localhost ~]$ echo | awk  'BEGIN{print test}' test="$test"         

 

这种变量在:BEGIN的action不能获得。

2.BEGIN程序块中变量

[chengmo@localhost ~]$ test='awk code'                                
[chengmo@localhost ~]$ echo | awk -v test="$test" 'BEGIN{print test}'
awk code
[chengmo@localhost ~]$ echo | awk -v test="$test" '{print test}'    
awk code

 

格式如:awk –v 变量名=变量值 [–v 变量2=值2 …] 'BEGIN{action}’  注意:用-v 传入变量可以在3中类型的action 中都可以获得到,但顺序在  action前面。

  

3.获得环境变量

[chengmo@localhost ~]$ awk  'BEGIN{for (i in ENVIRON) {print i"="ENVIRON[i];}}'
AWKPATH=.:/usr/share/awk
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SELINUX_LEVEL_REQUESTED=
SELINUX_ROLE_REQUESTED=
LANG=en_US.UTF-8
.......

 

只需要调用:awk内置变量 ENVIRON,就可以直接获得环境变量。它是一个字典数组。环境变量名 就是它的键值。

参考以上例子:

 

 

例子一:

root@rac0 tmp]# cat -n a1;cat -n b1;cat -n a.awk
     1  1 aa 5
     2  1 bbb 55
     3  1 ccc 555
     1  2 a
     2  2 b
     3  2 c
     1
     2  BEGIN {
     3
     4      printf "in begin ,n=%d/n", n;
     5      for (i = 0; i < ARGC; i++)
     6          printf "/tARGV[%d] = %s/n", i, ARGV[i]
     7  }
     8  {print n,$n}
     9  END   { printf "in end n=%d/n", n; }
[root@rac0 tmp]# awk -f a.awk -v n=1 n=3  a1 n=2 b1 
in begin ,n=1
        ARGV[0] = awk
        ARGV[1] = n=3
        ARGV[2] = a1
        ARGV[3] = n=2
        ARGV[4] = b1
3 5
3 55
3 555
2 a
2 b
2 c
in end n=2

 

看点:

1:-v,-f等option参数,不列入ARGV
2:-v的参数,要求在文件类参数(包括不加-v的var=text)之前
3:-v的效果,在BEGIN之前
4:n=3,n=2的效果

 

例子二:

比如要用awk计算某些单词在某些文件(列可能不同)出现个数,除了在程序里指定列,还可以在命令行里进行指定,简单而清晰
[root@rac0 tmp]# cat words1
fqef word4
wfww word3
[root@rac0 tmp]# cat words2
word4 aaa
word2 fwww
word1 fwwww
[root@rac0 tmp]# awk '{a[$n]++}END{for(b in a)print b,a[b]}' n=2 words1 n=1 words2
word1 1
word2 1
word3 1
word4 2

 

 

 

 

===================

第二部分,awk传参数给shell

 

这个就涉及到进程间通信了,因为shell调用起来的awk实际的执行环境是shell脚本运行进程的一个子进程,子进程原则上除了继承到自身环境上的变量外,无法对父进程的环境进行访问和修改的,所以在awk里执行system()变量附值,也更也不了shell参数

 

那么,如何做?

 

之前在cu上有讨论过函数调用的变量附值 ,回帖粘过来,不再展开了呵

 

(函数对shell变量更改)通常可以用这么几个办法

1:用全局变量附值(这种方法不适用于awk,下边有描述)
var=
func(){ var=blabla; };
func

2:用命令替换附值
func(){ echo blabla; };
var=$(func)

3:eval
(注,在这个例子中倒显得有点烦索,其实eval一个经典的用法就是用来脚本之间传递参数用的,毕竟进程间环境无法相互涉及)
var=
fun(){ echo "var=blabla";};
cmd=$(fun)
eval $cmd
echo $var

4:ipc...

 

unix系最常用的ipc莫过于管道

    func(){ echo "var=blabla" }
    func | read line
    eval $line


下边有个例子,是以前以前用过的一个例子,用的是命名管道
[oracle@rac2 tmp]$ cat -n test.sh
     1
     2
     3  mkfifo t;
     4
     5  a=0;
     6  b=0;
     7  awk 'BEGIN{print "a=1;b=2";print "end";}' >t &
     8
     9  while read c
    10  do
    11          test "$c" == "end"  && break;
    12          eval $c
    13  done <t
    14
    15  echo $a,$b;
    16
    17  rm t
    18
    19

 


注一:以上函数调用时增加参数不影响使用
注二:除了第一个方法:全局变量外,另外三种方法其实也广泛用到其他函数(如awk)更改shell变量值的应用上,因为subshell所在的子进程并不能更改到父进程的环境表,更改全局变量在这种情况下没效果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值