在shell程序中引入参数,shell程序就会灵活很多。本文首先简单介绍参数传递中的一些基本知识点,再通过一个通讯录的举例来加深对shell编程中参数传递的理解。
1. 参数的引用
当运行shell程序时,shell会自动将命令行中第一个参数保存在变量1中,第二个参数保存在变量2中,依次类推。因此,当需要在shell程序中使用这些参数时,便可以通过$1和$2这样的方法来引用。比如:
edsionte@edsionte-laptop:~/shelltest$ cat myargs echo "\"$1\" \"$2\" was passed" edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu "edsionte" "wu" was passed edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte "edsionte" "" was passed edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu me "edsionte" "wu" was passed
通过上述举例可以看到,命令行中的第n个参数会自动传递给相应的特殊变量n。通过$n就可以在shell程序中对其进行引用;当引用未赋值的特殊变量时,其结果将会显示空。
2. #变量
每当shell程序运行时,特殊变量#中就会保存此次shell程序中键入的参数个数。比如:
echo "There are $# arguments passed" echo "\"$1\" \"$2\" was passed" edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte There are 1 arguments passed "edsionte" "" was passed
命令行中的参数是以空格作为间隔。因此,下面这种结果也很合理:
edsionte@edsionte-laptop:~/shelltest$ ./myargs "edsionte wu" There are 1 arguments passed "edsionte wu" "" was passed edsionte@edsionte-laptop:~/shelltest$ name="edsionte wu" edsionte@edsionte-laptop:~/shelltest$ ./myargs $name There are 2 arguments passed "edsionte" "wu" was passed
3. *变量
特殊变量*中会保存shell程序运行时用户键入的所有参数。在参数不确定或参数数目易变时,该变量就很有用。
edsionte@edsionte-laptop:~/shelltest$ cat myargs echo "There are $# arguments passed" echo "\"$*\" was passed" edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu is me There are 4 arguments passed "edsionte wu is me" was passed edsionte@edsionte-laptop:~/shelltest$ ./myargs edsionte wu There are 2 arguments passed "edsionte wu" was passed
4. 通信录举例
查找用户
现在需要通过用户姓名从通信录info中查找一个用户的个人信息。我们通过编写shell程序lu来实现这个功能。最简单的程序为:
edsionte@edsionte-laptop:~/shelltest$ cat info edsionte wu:male:xian:18717375182 sen wang:female:hanzhong:15678675545 ting li:male:guangzhou:15784859345 jedsionte:male:xian:13556567884 edison:male:hongkong:1384742488 yun zhang:female:beijing:18654737473 edsionte@edsionte-laptop:~/shelltest$ cat lu # look someone up in the info book grep $1 info edsionte@edsionte-laptop:~/shelltest$ ./lu edsionte edsionte wu:male:xian:18717375182 jedsionte:male:xian:13556567884
这个结果似乎并不令人满意,因为我们想找用户名为edsionte的用户。不过这个问题很好解决,我们可以这样改进程序:
edsionte@edsionte-laptop:~/shelltest$ cat lu # look someone up in the info book grep ^$1 info edsionte@edsionte-laptop:~/shelltest$ ./lu edsionte edsionte wu:male:xian:18717375182
如果我们想通过全名edsionte wu来查找用户信息,就应该用双引号将全名作为一个整体引入其中。这样看似很完美,可是结果却不尽人意:
edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu" grep: wu: 没有那个文件或目录 info:edsionte wu:male:xian:18717375182
这是因为虽然edsionte wu作为一个参数传递给特殊变量1,但是shell将其替换后,grep命令并不认为edsionte wu是一个参数,而是将wu作为目标文件之一。为了避免这种情况,我们应该这样改进程序:
edsionte@edsionte-laptop:~/shelltest$ cat lu # look someone up in the info book grep "^$1" info edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu" edsionte wu:male:xian:18717375182
这样就可以满足我们要求了。但是,如果info中的信息如下所示,那么上述lu程序还是不算完美。比如:
edsionte@edsionte-laptop:~/shelltest$ cat info edsionte wu:male:xian:18717375182 sen wang:female:hanzhong:15678675545 edsionte wuee:male:xian:18717375182 ting li:male:guangzhou:15784859345 jedsionte:male:xian:13556567884 edison:male:hongkong:1384742488 yun zhang:female:beijing:18654737473 edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu" edsionte wu:male:xian:18717375182 edsionte wuee:male:xian:18717375182
因此,我们也应该在参数的尾部也做一些“手脚”,使得grep命令只匹配我们所传递的参数:
edsionte@edsionte-laptop:~/shelltest$ cat lu # look someone up in the info book grep "^$1:" info edsionte@edsionte-laptop:~/shelltest$ ./lu "edsionte wu" edsionte wu:male:xian:18717375182
至此,查找程序完成。
添加用户
当向通讯录中增添新用户信息时,我们必须再编写一个add程序。增加用户程序很简单:
edsionte@edsionte-laptop:~/shelltest$ cat add # add someone to the info book echo "$1:$2:$3:$4" >> info edsionte@edsionte-laptop:~/shelltest$ ./add elva female taibei 1335676567 edsionte@edsionte-laptop:~/shelltest$ ./lu elva elva:female:taibei:1335676567
>>使得新的信息会追加到原文件的末尾。在上述命令的基础上,我们还可以再增加按姓名排序的功能:
edsionte@edsionte-laptop:~/shelltest$ cat add # add someone to the info book echo "$1:$2:$3:$4" >> info sort -o info info edsionte@edsionte-laptop:~/shelltest$ cat info edison:male:hongkong:1384742488 edsionte wuee:male:xian:18717375182 edsionte wu:male:xian:18717375182 elva:female:taibei:1335676567 jedsionte:male:xian:13556567884 sen wang:female:hanzhong:15678675545 ting li:male:guangzhou:15784859345 yun zhang:female:beijing:18654737473
添加程序结束。
删除用户
有了上述两个程序的基础,删除用户程序则变得容易很多。首先通过sed命令将完全匹配给定人名的用户信息从info中删除;因为sed命令并不改变info文件本身的内容,因此需要将sed的输出结果暂存至缓冲区;最后通过mv命令替换文件名即可。
edsionte@edsionte-laptop:~/shelltest$ cat del # delete the given user from info sed "/^$1:/d" info > /tmp/info mv /tmp/info ./info edsionte@edsionte-laptop:~/shelltest$ ./del elva edsionte@edsionte-laptop:~/shelltest$ cat info edison:male:hongkong:1384742488 edsionte wuee:male:xian:18717375182 edsionte wu:male:xian:18717375182 jedsionte:male:xian:13556567884 sen wang:female:hanzhong:15678675545 ting li:male:guangzhou:15784859345 yun zhang:female:beijing:18654737473
随着对shell编程的深入理解,上述通讯录程序还可以不断完善。