注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

如何给awk传递外部变量  

2013-08-27 23:58:10|  分类: 脚本语言 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、大致的问题
一般来说,awk都是被shell调用的,而这个shell通常在脚本中才有意义,如果是在命令行中的一是只需,那可以随意挥洒、尽情发挥。主要是这个脚本可能以后还要被人审视。就像你说欠你十块,随便一说,并不当真,但是如果要写个欠条,立个合同,那就要斟酌斟酌了。
假设说awk需要读取一个配置文件的内容,而这个配置文件的位置不能在awk中写入,而需要从外部把这个名字传递给awk,此时该如何实现。
二、使用转义
大部分情况下,我们都是通过单引号来在命令行中写上将要执行的awk指令,原因很简单,由于awk中对于record的引用也是通过美元符号来实现的,如果使用双引号则bash会早于awk对变量引用进行展开,这通常不是我们希望的效果。但是shell同样支持对于展开的转义,所以使用双引号也可以,只要把awk命令中所有的空格、双引号、变量引用符号都转义一下即可。
[root@Harry ~]# echo foo=bar | awk "{ print \$1}"
foo=bar
这种方法对于简单的命令使用起来没什么问题,但是如果命令复杂,并且里面有双引号(通常是少不了的,因为awk毕竟是为了执行print或者printf),可读性较差,但是如果是简单命令,这是一个可行的选择。
三、使用引号分割
这种方法就是利用shell的变脸自动拼接功能,只要没有遇到shell的分隔符(元字符及空白),那么一个单词就没有结束。所以在需要使用shell变量的地方,我们单独使用"引用",但是和其它地方使用单引号连接。
[root@Harry ~]#   awk 'END { print'"\"$foo\""'}' /dev/null
bar
这个例子比较特殊,但是大致就是这个意思。
四、使用awk命令行的 -v选项
       -v var=val
       --assign var=val
              Assign the value val to the variable var, before execution of the  pro-
              gram  begins.  Such variable values are available to the BEGIN block of
              an AWK program.
[root@Harry ~]# awk -vfoo=bar 'END {print foo}' /dev/null
bar
五、使用eval
这个命令在make中有、在shell中也有,但是在早期的awk版本中没有,至少在
[root@Harry ~]# awk --version
GNU Awk 3.1.7
Copyright (C) 1989, 1991-2009 Free Software Foundation.

这个版本里没有,至少在4.10版本中有。我遇到的环境中大部分是3.X的,没有eval这个功能。
六、eval的意义
这个命令我们其实平常用的比较少,但是在有些时候比较有用。例如有些配置文件中可能经常会有类似excel格式的内容,简单的说,例如
      foo 1234
     bar 5678
这种形式的配置文件,而在shell中我们希望能够动态的像变量一样引用每个变量的值(当然这里如果配置文件中变量名比较特殊可能会和shell自定义变量冲突的问题)。此时就可以使用shell的eval命令来根据配置文件生成简单的变量赋值命令,之后就可以像变量一样来引用这些数值了。
[root@Harry ~]# echo foo 1234 | while read var val ; do echo $foo ;eval $var=$val ; echo $foo; done
bar
1234
[root@Harry ~]#
七、使用一个空格
这个方法比较投机,在shell的双引号中,如果美元符号后面跟的不是一个可识别的符号,例如空格,那么shell不会对这个美元符号做任何操作,原样保留,另一方面,awk则不要求美元符号和接下来的变量直接相邻,所以可以对于其中的所有美元符号之间添加一个空格。
 [root@Harry tapset]# echo hello world | awk "{print $$ $ 2}"
12140world
可以看到,两个连在一起的美元被shell取值为当前shell的pid,而接下来的2和美元之间有空格,所以shell不会解析,而awk则不离不弃,照样解释了这个对于field的引用。
八、make中basename和shell basename意义的不同
make中
$(basename names...)
Extracts all but the suffix of each file name in names. If the file name contains a period, the basename is everything starting up to (and not including) the last period. Periods in the directory part are ignored. If there is no period, the basename is the entire file name. For example,
          $(basename src/foo.c src-1.0/bar hacks)

produces the result ‘src/foo src-1.0/bar hacks’. 

shell中
EXAMPLES
       basename /usr/bin/sort
              Output "sort".

       basename include/stdio.h .h
              Output "stdio".
[root@Harry ~]# basename include/stdio.h
stdio.h
两者意义不同,由于make的先入为主概念,导致对于shell的这个命令一直望文生义。
  评论这张
 
阅读(682)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017