热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

详细介绍Linuxshell脚本基础学习(二

接详细介绍Linuxshell脚本基础学习(一)我们来看一下shell中Heredocuments和函数的使用。

接详细介绍Linux shell脚本基础学习(一)我们来看一下shell中Here documents和函数的使用。

6. Here documents

HERE Document是bash里面定义块变量的途径之一

定义的形式为:

命令<

...

...

...

HERE

它的作用即可以用来定义一段变量,会把命令和HERE之间的内容利用转向输入的方式交给该命令去处理。其中HERE相当于标记,可以是任何的字符串。注意后一个HERE的最后不要有空格,否则会报错。

使用HERE Document用在变量设定:

view sourceprint?
1 [aa@aa shell]$ wow='Wow,great!'

2 [aa@aa shell]$ m1=$(cat <

3 > Line 1 is good. 

4 > They are jack,marry and john. 

5 > $wow 

6 > Here 

7 > ) 

8 [aa@aa shell]$ echo $m1 

9 Line 1 is good. They are jack,marry and john. Wow,great!
     注意这里HERE还有一个特殊的用法 :
     就是在HERE前面加上-或者给HERE加上' ',加上-表明下述文字段所有TAB键将全部忽略,加上' '表明以下凡是变量定义用到了' ',将会使变量呈现所见即所得的形式,也即关闭变量替换;如果加上的是" "双引号,则会进行变量替换。

view sourceprint?
1 [aa@aa shell]$ wow='Wow,great!'

2 [aa@aa shell]$ m1=$(cat <<'Here'

3 > Line 1 is good. 

4 > They are jack,marry and john. 

5 > $wow 

6 > Here 

7 > ) 

8 [aa@aa shell]$ echo $m1 

9 Line 1 is good. They are jack,marry and john. $wow
注意:这里的$wow被原样输出了。至于加上-的效果这里不细说,大家可自行测试。

它也可以用来定义一段注释 ,利用HERE Document做多行批注,方法是:

:< 这是第一行批注
这是第二行批注
这是第三行批注
其它行,类推
HERE


:代表什么都不做
     原本bash只支持单行批注(用#表示),现就可用于多行注释了,此处不细说。

当要将几行文字传递给一个命令时,here documents是一种不错的方法。对每个脚本写一段帮助性的文字是很有用的,此时如果我们四有那个 here documents就不必用echo函数一行行输出。 一个 "Here document" 以 <<开头,后面接上一个字符串,这个字符串还必须出现在here document的末尾。

下面我们来看一个例子,在该例子中,我们对多个文件进行重命名,并且使用here documents打印帮助:

view sourceprint?
01 #!/bin/sh 

02 # we have less than 3 arguments. Print the help text: 

03 if [ $# -lt 3 ] ; then 

04 cat <

05 -- renames a number of files using sed regular expressions 

06 USAGE: $0 'regexp' 'replacement' files... 

07 EXAMPLE: rename all *.HTM files in *.html: 

08 $0 'HTM$' 'html' *.HTM 

09 help 

10 exit 0 

11 fi

12        

13 OLD="$1"

14 NEW="$2"

15 # The shift command removes one argument from the list of 

16 # command line arguments. 

17 shift

18 shift

19 # $* contains now all the files: 

20 for file in $*; do

21         if [ -f "$file" ] ; then

22                 newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"` 

23                 if [ -f "$newfile" ]; then

24                         echo "ERROR: $newfile exists already"

25                 else

26                         echo "renaming $file to $newfile ..."

27                         mv "$file" "$newfile"

28                 fi

29         fi

30 done
执行脚本:

view sourceprint?
1 [aa@aa shell]$ ll 

2 总用量 4 

3 -rw-rw-r--. 1 yongli yongli   0 2月  17 14:06 a.html 

4 -rw-rw-r--. 1 yongli yongli   0 2月  17 14:06 b.html 

5 -rw-rw-r--. 1 yongli yongli   0 2月  17 14:06 c.html 

6 -rwxrwxr-x. 1 yongli yongli 681 2月  17 14:21 here_doc.sh
view sourceprint?
1 [aa@aa shell]$ /data/shell/here_doc.sh 

2        

3 -- renames a number of files using sed regular expressions 

4 USAGE: /data/shell/here_doc.sh 'regexp' 'replacement' files... 

5 EXAMPLE: rename all *.HTM files in *.html: 

6 /data/shell/here_doc.sh 'HTM$' 'html' *.HTM
view sourceprint?
1 [aa@aa shell]$ /data/shell/here_doc.sh 'htm$' 'html' *.htm 

2        

3 renaming a.htm to a.html ... 

4 renaming b.htm to b.html ... 

5 renaming c.htm to c.html ...
       下面让我们详细说明下。

       第一个if表达式判断输入命令行参数是否小于3个 (特殊变量$#表示包含参数的个数) 。如果输入参数小于3个,则将帮助文字传递给cat命令,然后由cat命令将其打印在屏幕上。打印帮助文字后程序退出($0: 表示当前脚本的名称)。

       如果输入参数等于或大于3个,我们 就将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW。

       下一步,我们使用shift命令将第一个和第二个参数从参数列表中删除,这样原来的第三个参数就成为参数列表$*的第一个参数。

       然后我们开始循环,命令行参数列表被一个接一个地被赋值给变量$file。

       接着我们判断该文件是否存在,如果存在则通过sed命令搜索和替换来产生新的文件名。然后将反短斜线内命令结果赋值给newfile。这样我们就达到了我们的目的:得到了旧文件名和新文件名。然后使用mv命令进行重命名。

       这里我们再看一个实例,利用HERE Document,打包C(或其它程序语言)的原始码。这是Cracker散布安全漏洞程序,最喜欢的方法。

view sourceprint?
01 #!/bin/bash   

02 # Filename:create_prg.sh   

03 echo "creating hello.c..."

04 echo

05 cat <<'EOF' > hello.c   

06 #include    

07 int main()   

08 {   

09         printf("Hello world!\n");   

10         return 0;   

11 }   

12 EOF 

13 echo "compiling hello.c..."

14 #compile hello.c,create the excutable file   

15 gcc -o hello hello.c 

16        

17 #if compile successfully,then excute it   

18 if [ $? -eq 0 ];then

19         echo "excute hello..."

20         chmod u+x hello 

21         ./hello 

22 else

23         echo 'Compile Error:hello.c'

24 fi
7.函数

       函数是一串命令的集合,函数可以把大的命令集合分解成若干较小的任务。编程人员可以基于函数进一步的构造更复杂的Shell 程序,而不需要重复编写相同的代码。

       基本形式:

       function_name()
       {
       command1
       command2
       …
       commandN
       }

       对函数结构进行解释:
       其中标题:函数名,函数体:函数内的命令集合,在编写脚本时要注意标题名应该唯一,如果不唯一,脚本执行时会产生错误。
       在函数名前可以加上关键字function,但加上和省略关键字function对脚本的最终执行不产生任何影响。
       函数体中的命令集合必须含有至少一条命令,即函数不允许空命令,这一点和C语言不同。
       函数之间可通过参数、函数返回值交互,函数在脚本中出现的次序可以是任意的,但是必须按照脚本中的调用次序执行这些函数。
       向函数传递参数
       在bash Shell编程中,向函数传递的参数仍然是以位置参数的方式来传递的,而不能传递数组等其它形式变量,这与C语言或Java语言中的函数传递是不同的。

       function1.sh

view sourceprint?
01 #!/bin/bash 

02        

03 half() 

04 { 

05      let "n = $1"

06      let "n = n/2"

07      echo "In function half() n is $n"

08 } 

09 if [ -z $1 ];then

10     echo 'Please input number m.'

11     echo "Uage:$0 number"

12     echo "Example:$0 2"

13     exit 0 

14 fi

15 let "m = $1"

16 echo "Before the function half() is called, m is $m"

17 half $m 

18 echo "After the function half() is called, m is $m"
       在Linux Shell编程中,函数还可传递间接参数,但该方式传递方式远远没有C语言和Java语言灵活,而只能使用间接变量引用来传递参数,这种方式是一种笨拙的间接参数传递方式。

       function2.sh

view sourceprint?
01 #!/bin/bash 

02        

03 ind_func() 

04 { 

05     echo " $1"

06 } 

07        

08 if [ -z $1 ];then

09         echo 'Please input arguments.'

10         echo "Uage:$0 args"

11         echo "Example:$0 a"

12         exit 0 

13 fi

14        

15 parameter=ind_arg 

16 ind_arg=Hello 

17        

18 ind_func "$parameter"

19        

20 ind_func "${!parameter}"

21        

22 echo "***********************"

23        

24 ind_arg=World 

25 ind_func "$parameter"

26 ind_func "${!parameter}"
       函数返回值
       有时需要脚本执行完成后返回特定的值来完成脚本的后继操作,这些特定的值就是函数返回值。在Linux Shell编程中,函数通过return返回其退出状态,0表示无错误,1表示有错误。在脚本中可以有选择的使用return语句,因为函数在执行完最后一条语句后将执行调用该函数的地方执行后继操作。

       function3.sh

view sourceprint?
01 #!/bin/bash 

02        

03 show_week() 

04 { 

05     echo -n "What you input is: "

06     echo "$1"

07        

08     case $1 in

09 ) 

10         echo "Today is Sunday. "

11         return 0;; 

12 ) 

13         echo "Today is Monday. "

14         return 0;; 

15 ) 

16         echo "Today is Tuesday. "

17         return 0;; 

18 ) 

19         echo "Today is Wednesday. "

20         return 0;; 

21 ) 

22         echo "Today is Thursday. "

23         return 0;; 

24 ) 

25         echo "Today is Friday. "

26         return 0;; 

27 ) 

28         echo "Today is Saturday. "

29         return 0;; 

30     *) 

31         return 1;; 

32     esac 

33 } 

34        

35 if show_week "$1"

36 then

37     echo "What you input is right! "

38 else

39     echo "What you input is wrong! "

40 fi

41 exit 0
       脚本放置多个函数
       可以在脚本中放置多个函数,脚本执行时按照调用函数的顺序执行这些函数.

       function4.sh

view sourceprint?
01 #!/bin/bash 

02        

03 show_week() 

04 { 

05     for day in Monday Tuesday Wednesday Thursday Friday Saturday Sunday 

06     do

07         echo  -n "$day "

08     done

09     echo ""

10 } 

11        

12 show_number() 

13 { 

14     for(( integer = 1; integer <= 7; integer++ )) 

15     do

16         echo -n "$integer "

17     done

18             

19     echo ""

20 } 

21        

22 show_square() 

23 { 

24     i=0 

25            

26     until [[ "$i" -gt 7 ]] 

27     do

28         let "square=i*i"

29         echo "$i * $i = $square"

30         let "i++"

31     done

32 } 

33        

34 show_week 

35 show_number 

36 show_square
       函数相互调用
       在Linux Shell编程中,函数之间可以相互调用,调用时会停止当前运行的函数转去运行被调用的函数,直到调用的函数运行完,再返回当前函数继续运行。
       一个函数调用多个函数
       在Linux Shell编程中允许一个函数调用多个函数,在该函数调用其他函数时同样需要按照调用的顺序来执行调用的函数。
       局部变量和全局变量
       在Linux Shell编程中,可以通过local关键字在Shell函数中声明局部变量,局部变量将局限在函数范围内。此外,函数也可调用函数外的全局变量,如果一个局部变量和一个全局变量名字相同,则在函数中局部变量将会覆盖掉全局变量.
       函数递归
       Linux Shell中可以递归调用函数,即函数可以直接或间接调用其自身。在递归调用中,主调函数又是被调函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层。

       function5.sh

view sourceprint?
01 #!/bin/bash 

02        

03 #递归调用函数 

04 foo() 

05 { 

06     read y 

07     foo $y 

08     echo "$y"

09 } 

10        

11 #调用函数 

12 foo 

13 exit 0
       使用局部变量进行递归一般是针对数值运行来使用的。阶乘运算是一个使用局部变量的递归调用过程,实现了n! 的运算,其可以通过下面的公式表示:
       n!=1 (n=0)
       n!=n*(n-1)! (n>=1)
       按照该公式可实现对阶乘的运算,由于该阶乘运算中存在终止条件“0!=1”,所以可以使用函数递归来实现该运算。

       function6.sh

view sourceprint?
01 #!/bin/bash 

02 #$1的阶乘 

03        

04 fact () 

05 { 

06     local num=$1 

07     if [ "$num" -eq 0 ] 

08     then

09         factorial=1 

10     else

11         let "decnum=num-1"

12         fact $decnum 

13         let "factorial=$num * $?"

14     fi

15     return $factorial 

16 } 

17        

18 if [ -z $1 ];then

19         echo 'Please input an intger number argument.'

20         echo "Uage:[$0 args]"

21         echo "Example:[$0 5]"

22         exit 0 

23 fi

24        

25 fact $1 

26 echo "Factorial of $1 is $?"

27 exit 0
        ok.到这里先暂告一段落,其他的后续写出。


推荐阅读
  • linux用通配符排除指定字符结尾文件的一种方法,Go语言社区,Golang程序员人脉社 ... [详细]
  • 如何利用正则表达式(regexp)实现高效的模式匹配?本文探讨了正则表达式在编程中的应用,并分析了一个示例程序中存在的问题。通过具体的代码示例,指出该程序在定义和使用正则表达式时的不当之处,旨在帮助读者更好地理解和应用正则表达式技术。 ... [详细]
  • Docker入门指南:初探容器化技术
    Docker入门指南:初探容器化技术摘要:Docker 是一个使用 Go 语言开发的开源容器平台,旨在实现应用程序的构建、分发和运行的标准化。通过将应用及其依赖打包成轻量级的容器,Docker 能够确保应用在任何环境中都能一致地运行,从而提高开发和部署的效率。本文将详细介绍 Docker 的基本概念、核心功能以及如何快速上手使用这一强大的容器化工具。 ... [详细]
  • 在尝试为 Unity 编译一个简单的 Java 库时,运行 `ant jar` 命令后遇到了 Java I/O 异常。具体错误信息为“无法启动程序 ${aAPT},错误代码 2”,这通常表示指定的文件或目录不存在。此问题可能是由于环境配置不正确或路径设置有误导致的。建议检查相关路径和环境变量,确保所有依赖项都已正确安装和配置。 ... [详细]
  • 【Linux进阶指南】第一阶段第三课:体验与部署Ubuntu系统
    在正式踏上Linux学习之旅之前,本课程将引导你深入体验和部署Ubuntu系统。通过详细的操作步骤和实践演练,你将掌握Ubuntu的基本安装、配置及常用命令,为后续的进阶学习打下坚实的基础。此外,课程还将介绍如何解决常见问题和优化系统性能,帮助你更加高效地使用Ubuntu。 ... [详细]
  • 1. 设置用户密码:使用 `slappasswd` 工具生成加密密码,确保账户安全。具体步骤如下:输入命令 `slappasswd -s NewPassword`,系统将提示重新输入新密码,并生成加密后的哈希值 {SSHA}xxxxxxxxxxxxxxxxx。2. 编写配置文件:编辑 `vildapus` 配置文件,添加必要的用户账户信息,以确保新用户能够顺利登录系统。 ... [详细]
  • 解决CentOS 6.4系统中sda磁盘包含BIOS RAID元数据的问题及专业应对策略
    解决CentOS 6.4系统中sda磁盘包含BIOS RAID元数据的问题及专业应对策略 ... [详细]
  • 技术日志:Ansible的安装及模块管理详解 ... [详细]
  • 在Linux系统中,为了提高安全性,可以通过设置命令执行超时和用户超时注销来防止因用户长时间未操作而带来的安全隐患。具体而言,可以通过编辑 `/etc/profile` 文件,添加或修改相关参数,确保用户在指定时间内无操作后自动注销。此外,还可以利用 `timeout` 命令来限制特定命令的执行时间,进一步增强系统的稳定性和安全性。 ... [详细]
  • 本文详细介绍了使用响应文件在静默模式下安装和配置Oracle 11g的方法。硬件要求包括:内存至少1GB,具体可通过命令`grep -i memtotal /proc/meminfo`进行检查。此外,还提供了详细的步骤和注意事项,确保安装过程顺利进行。 ... [详细]
  • 在Linux系统中,目录结构遵循文件系统层次标准(FHS),确保了系统的组织性和可维护性。其中,`/bin`目录是FHS要求必须存在的目录之一,主要存放了在单用户维护模式下仍可执行的基本命令和工具。这些命令不仅对root用户可用,普通用户也能使用,以确保系统在最小化运行状态下仍能进行基本的操作和管理。 ... [详细]
  • 如何将PHP文件上传至服务器及正确配置服务器地址 ... [详细]
  • 在Linux系统中,原本已安装了多个版本的Python 2,并且还安装了Anaconda,其中包含了Python 3。本文详细介绍了如何通过配置环境变量,使系统默认使用指定版本的Python,以便在不同版本之间轻松切换。此外,文章还提供了具体的实践步骤和注意事项,帮助用户高效地管理和使用不同版本的Python环境。 ... [详细]
  • 系统管理员可以通过多种方法实时监控Linux系统中的用户活动,包括当前已登录的用户及其正在进行的操作。利用特定的命令和工具,管理员可以轻松获取这些信息,确保系统的安全性和稳定性。例如,使用`who`、`w`或`last`等命令可以快速查看当前登录的用户及其活动详情。 ... [详细]
  • 本文探讨了将PEBuilder转换为DIBooter.sh的方法,重点介绍了如何将DI工具集成到启动层,实现离线镜像引导安装。通过使用DD命令替代传统的grub-install工具,实现了GRUB的离线安装。此外,还详细解析了bootice工具的工作原理及其在该过程中的应用,确保系统在无网络环境下也能顺利引导和安装。 ... [详细]
author-avatar
罂粟花的美童鞋
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有