(3)awk读取shell中的变量
可以使用-v选项实现功能
b=1
b=1cat f
apple
1
|
$awk -v
var
=$b
'{print var, $var}'
file
|
1 apple
至于有没有办法把awk中的变量传给shell呢,这个问题我是这样理解的。shell调用awk实际上是fork一个子进程出来,而子进程是无法向父进程传递变量的,除非用重定向(包括管道)
a=
(awk′print$b,′$b′′f)
(awk′print$b,′$b′′f)echo $a
apple 1
(4)输出重定向 , awk是子进程,如何传出awk中的变量值
awk的输出重定向类似于shell的重定向。重定向的目标文件名必须用双引号引用起来。
awk′
awk′4 >=70 {print
1,
1,2 > "destfile" }' filename
awk′
awk′4 >=70 {print
1,
1,2 >> "destfile" }' filename
(5)awk中调用shell命令:
1)使用管道
awk中的管道概念和shell的管道类似,都是使用"|"符号。如果在awk程序中打开了管道,必须先关闭该管道才能打开另一个管道。也就是说一次只能打开一个管道。shell命令必须被双引号引用起来。“如果打算再次在awk程序中使用某个文件或管道进行读写,则可能要先关闭程序,因为其中的管道会保持打开状态直至脚本运行结束。注意,管道一旦被打开,就会保持打开状态直至awk退出。因此END块中的语句也会收到管道的影响。(可以在END的第一行关闭管道)”
awk中使用管道有两种语法,分别是:
awk output | shell input
shell output | awk input
对于awk output | shell input来说,shell接收awk的输出,并进行处理。需要注意的是,awk的output是先缓存在pipe中,等输出完毕后再调用shell命令 处理,shell命令只处理一次,而且处理的时机是“awk程序结束时,或者管道关闭时(需要显式的关闭管道)”
1
|
$awk
'/west/{count++} {printf "%s %s\t\t%-15s\n", $3,$4,$1 | "sort +1"} END{close "sort +1"; printf "The number of sales pers in the western"; printf "region is " count "." }'
datafile
|
(解释:/west/{count++}表示与“wes”t进行匹配,若匹配,则count自增)
printf函数用于将输出格式化并发送给管道。所有输出集齐后,被一同发送给sort命令。必须用与打开时完全相同的命令来关闭管道(sort +1),否则END块中的语句将与前面的输出一起被排序。此处的sort命令只执行一次。
在shell output | awk input中awk的input只能是getline函数。shell执行的结果缓存于pipe中,再传送给awk处理,如果有多行数据,awk的getline命令可能调用多次。
$awk 'BEGIN{ while(("ls" | getline d) > 0) print d}' file
(6)主进程直接获取子进程awk的输出值:
1. var=· shell_cmd | awk ' print $1 '
2.var=$(shell_cmd | awk ' print $1 ') ·
3.eval
(注,在这个例子中倒显得有点烦索,其实eval一个经典的用法就是用来脚本之间传递参数用的,毕竟进程间环境无法相互涉及)
var=
fun(){ echo "var=blabla";};
cmd=$(fun)
eval $cmd
echo $var
(7)子进程awk调用主进程shell的变量
1、获得普通外部变量
[chengmo@ localhost ~]$ echo | awk ‘BEGIN{print test}’ test=”$test”
这种变量在:BEGIN的action不能获得。
2.BEGIN程序块中变量
2
3
4
5
|
[
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.获得环境变量
1
2
3
4
5
6
7
|
[
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,就可以直接获得环境变量。它是一个字典数组。环境变量名 就是它的键值。
4.直接使用shell变量。
格式如下:awk '{print "'$shell_var'"}' filename,注意:先用双引号,再用单引号。
- #!/bin/sh
- var="test"
- awk '
- BEGIN{
- print "begin outputvar:" "'$var'"
- }
- {
- print "'$var'"
- }
- END{
- print "end outputvar:" "'$var'"
- } ' group_file3
5. 内部函数
5.1 字符串替换
sub(/regrexp/,"REPLACEMENT",target) target省略就是$0 , 可以是$1 $2 .. $10, 正则表达式要有/ / , REPLACEMENT 要有 “ ”
gsub( /regrexp/,"REPLACEMENT",target) (regular expression, substitution string)
gensub(regexp, replacement, “how”, target) 这个事gawk提供的一个通用型的函数,返回替换后的字符串。上两个返回替换的数目。
gensub确实不同于sub和gsub这2个工具,它有它更独特的魅力,下面我通过几个例子给大家讲解它的实际用法和独到之处。
- echo "11111" | awk 'BEGIN{FS=OFS=""}{$4="x";print}'
- 111x1
- echo "11111" | awk '{print $0=gensub("1","x",4)}'
111x1
echo "11111" | awk '{print $0=gensub("1","x","g")}'
xxxxx
[解析]
阁下是不是豁然开朗了很多?这就是gensub的便捷,在这里面不再需要字段分割符,用数字即可指定你要替换的某一位。g和G是指全局替换,要双引号标记起来。特别注意的是gensub是不会修改原记录的,所以要对$0进行一个赋值。“the modified string is returned as the result of the function and the original target string is not changed”。接下来我们再看看一个更复杂的运用。
- echo "unix linux" | awk '{print gensub(/(.+) (.+)/,"\\2 \\1","g")}'
linux unix
echo "xaax xbx xxx:xaax xbx xxx" | awk -F: -vOFS=":" '{$2=gensub(/x([^x]+)x/,"\\1YY",2,$2)}1'
xaax xbx xxx:xaax bYY xxx
[解析]
是不是觉得很眼熟?呵呵是的,就是sed的用法,对!还有正则。特别注意的是需要双斜杠噢。聪明的您以后一定会熟练gensub的用法的