Chinaunix首页 | 论坛 | 博客
  • 博客访问: 968667
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-11-26 18:03:11

8.12 interpreter files

本文针对execinterpreter文件的使用,用例子来检测了参数的传递。

经常看到一些开头是如下格式的脚本文件:

#! /bin/awk -f 等等。

这些文件还都是可执行的,但是他们又不同于linux系统本身的可执行文件的格式。但是都可以在命令行下用./a.out来启动他们,所以他们的执行一定有一个过程。

(一)使用#! xxx

有脚本myscript内容如下:

#!/bin/awk -f
BEGIN {
    for (i = 0; i < ARGC; i++)
        printf "ARGV[%d] = %s\n", i, ARGV[i]
    exit
}

 

其执行过程我觉得是如下的:

1.你在shell里面敲./myscript arg1 arg2

2Shell就认为你要执行一个外部命令,所以就fork 出一个子shell A

3.子shellA开始尝试用execlp执行./myscript却出错,因为它不是一个普通的可执行文件格式,于是shell A就认为它是一个脚本。

4.于是子shell A就打开myscrpt, 读取其第一行,发现是#! /bin/awk –f,那么shell就知道了原来这是一个awk脚本,需要由/bin/awk程序去处理,而且应该传递参数-fawk., 此外还有三个参数,分别是命令本身“./myscrpt”,以及arg0, arg1,这样shell就知道了所有的事情。

5.好了,exec awk吧,参数分别为:/bin/awk, -f, ./myscript, arg0, arg1

其中,/bin/awk是程序本身,注意脚本文件./myscript也成了参数。

你看,你调用了awk去处理文件./myscrpt,那么awk就会打开myscript,此时#!对于awk来说就是一段注释,awk就不会管他了。

总之,一共有一个子进程被fork出来。而且调用这些可执行的脚本的时候,我们没必要去关心究竟由谁去处理它,这些工作是由shell自己完成的。这是脚本的好处。

 

(二)不使用#! xxx

如果不使用#! /bin/awk –f这一行。比如我们有这样一个可执行文件:

awk 'BEGIN {

        for (i = 0; i < ARGC; i++)

            printf "ARGV[%d] = %s\n", i, ARGV[i]

        exit

    }' $*

那么其执行过程如下:

1.你在shell里面敲./myscript arg1 arg2

2Shell就认为你要执行一个外部命令,所以就fork 出一个子shell A

3.子shellA开始尝试用execlp执行./myscript却出错,因为它不是一个普通的可执行文件格式,于是shell A就认为它是一个脚本。

4. shell A打开这个文件,也没看到啥东西,直接上来就是awk ‘BEGIN’ { …..,多以对于这个shell来说你是在调用外部命令awk,所以,他怎会怎么做呢?

5. shell A fork一个子shell,然后在子shell里执行exec awk,参数呢就是/bin/awk, 以及你在这个脚本里调用awk时提供的参数,如果你想将脚本的参数arg1, arg2也传递给awk,就必须在脚本内部利用shell变量$1, $2显式作为传给awk的参数。而如果我们使用了#! Xxx,那么我们调用脚本时的参数就传给了awk本身,当然也包括脚本文件本身。

总之,如果不在一个脚本前加上#! Xxx,那么整体执行下来,需要多做一次fork,可见开销较大。

其实第一个脚本使用#! /bini/awk是一个awk脚本,第2个不使用#/bin/awk的脚本是一个shell脚本。可见使用shell脚本不如直接使用awk脚本效率高啊。

 

为了测试,写了个例子,如下:

(例子1

1.我们写了一个自己的名为awk的程序用来代替系统的awk:,好做测试。

这个程序仅仅是打印自己的参数。

#include

 

int main( int argc, char* argv[] )

{

       printf("in awk %d args:\n", argc );

       for( int i=0; i

       {

              printf("arg[%d]=", i);

              puts( argv[i] );

       }

}

2.然后将此程序编译成awk,然后覆盖/usr/bin/awk目录。

3.然后系一个脚本myscript内容如下:

#! /usr/bin/awk –f

可见仅有一句话,它的目的就是调用 awk程序。

4.我们的执行流程如下:

shaoting@desktopbj-LabSD:/home/shaoting/mytest> ./myscript2 222

in awk 4 args:

arg[0]=/usr/bin/awk

arg[1]=-f

arg[2]=./myscript2

arg[3]=222

可见,我们提供给脚本的参数也成了调用awk的参数

(例子2

1.依然使用上边的awk

2. 我们的脚本myscript2内容如下:

echo $0

echo $1

echo $2

awk -f 'kkak'

3. 执行流程如下:

shaoting@desktopbj-LabSD:/home/shaoting/mytest> ./myscript arg0 arg1

./myscript

arg0

arg1

in awk 3 args:

arg[0]=awk

arg[1]=-f

arg[2]=kkak

可见,在脚本内,$0, $1,$2对应的就是./myscript, arg0, arg1,他们仅仅是脚本的参数

awk输出的参数里,只有awk, -f , kkak即我们在脚本里调用awk时候的参数,而并不包括脚本的参数。

(例子三)这个例子是仿照书上的写的

    1Myscript3的内容如下:

#! /usr/bin/awk -f

BEGIN {

       for(i=0; i

              printf " arg[%d]=%s\n" , i, ARGV[i]

       exit               

}

执行流程:

shaoting@desktopbj-LabSD:/home/shaoting/mytest> ./myscript3 arg0 arg1

in awk 5 args:

arg[0]=/usr/bin/awk

arg[1]=-f

arg[2]=./myscript3

arg[3]=arg0

arg[4]=arg1

(2) myscript4的内容如下

awk 'BEGIN {

       for(i=0; i

              printf " arg[%d]=%s\n" , i, ARGV[i]

       exit               

}' $*

执行流程:(注意,$*并不包括”./myscript4”, 即不包括$0

shaoting@desktopbj-LabSD:/home/shaoting/mytest> ./myscript4 arg0 arg1

in awk 4 args:

arg[0]=awk

arg[1]=BEGIN {

           for(i=0; i

           printf " arg[%d]=%s\n" , i, ARGV[i]

           exit

}

arg[2]=arg0

arg[3]=arg1

 

总之,interpreter file的优点:

1.可以隐藏究竟要用哪个解释器来执行这个脚本

2.效率比使用shell脚本高,因为减少了fork

3.可以使用不同的shell来处理脚本,比如我们可以在cshbash之间做出选择。更灵活。

阅读(930) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~