精华内容
下载资源
问答
  • 脚本语言与编程语言的区别

    千次阅读 2019-03-06 21:34:47
    脚本语言对程序员提供了更高级的抽象,在这种语言中,有着更高级的数据...脚本语言是解释型语言,不需要提前编译,交互式脚本语言是最松散的类型定义,完全没有类型声明,只有在运行的时候会对动态类型检查。 ...

    脚本语言对程序员提供了更高级的抽象,在这种语言中,有着更高级的数据结构,例如列表和字典结构。

    脚本语言是解释型语言,不需要提前编译,交互式。

    脚本语言是最松散的类型定义,完全没有类型声明,只有在运行的时候会对动态类型检查。

     

    展开全文
  • 函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分 函数和shell程序比较相似,区别在于...

    1.函数介绍
    函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程
    它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分
    函数和shell程序比较相似,区别在于:
    Shell程序在子Shell中运行
    而Shell函数在当前Shell中运行。因此在当前Shell中,函数可以对shell中变量进行修改
    查看系统所有函数命令:declare -f
    查看func 1: declare -f func1
    函数在当前shell里生效

    2.定义函数
    函数由两部分组成:函数名和函数体
    help function
    语法一(最简洁):
    f_name (){
    …函数体…
    }
    语法二:
    function f_name {
    …函数体…
    }
    语法三(太啰嗦):
    function f_name () {
    …函数体…
    }
    示例:
    1. 测试函数,打印test function
    func1 ()
    {
    echo test function
    }
    2.匿名函数:
    false || {ls;exit;}
    echo hello
    发现么有打印hello,也没有定义函数名,但是它确实是执行了

    3函数使用
    函数的定义和使用:
    可在交互式环境下定义函数
    可将函数放在脚本文件中作为它的一部分
    可放在只包含函数的单独文件中
    调用:函数只有被调用才会执行
    调用:给定函数名
    函数名出现的地方,会被自动替换为函数代码
    函数的生命周期:被调用时创建,返回时终止

    函数里的变量建议加上local(局部变量,函数结束时自动销毁)

    4.脚本中的函数return和exit的区别
    return只是退出当前函数内的命令
    exit 则结束退出整个脚本的命令。

    5.引用函数的方法:
    . funcname 或 source funcname
    常用系统函数 /etc/init.d/functions

    1. /etc/init.d/functions里面的action函数,用来打印绿色[ OK ]或者红色[ FAILED ]
      用例,引用 action打印的函数
      . /etc/init.d/functions
      action “rm -rf /test” true
      action “rm -rf /test” false

    7.函数返回值
    函数有两种返回值:
    函数的执行结果返回值:
    (1) 使用echo等命令进行输出
    (2) 函数体中调用命令的输出结果
    函数的退出状态码:
    (1) 默认取决于函数中执行的最后一条命令的退出状态码
    (2) 自定义退出状态码,其格式为:
    return 从函数中返回,用最后状态命令决定返回值
    return 0 无错误返回。
    return 1-255 有错误返回

    8.交互式环境下定义和使用函数
    示例:
    dir() {

    ls -l
    }
    定义该函数后,若在$后面键入dir,其显示结果同ls -l的作用相同
    dir
    该dir函数将一直保留到用户从系统退出,或执行了如下所示的unset命令
    unset dir

    9.在脚本中定义及使用函数(最好把函数写成文件)
    函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用
    调用函数仅使用其函数名即可
    示例:
    cat func1

    !/bin/bash

    func1

    hello()
    {
    echo “Hello there today’s date is date +%F
    }
    echo “now going to the function hello”
    hello
    echo “back from the function”

    10.使用文件定义函数
    可以将经常使用的函数存入函数文件,然后将函数文件载入shell
    文件名可任意选取,但最好与相关任务有某种联系。例如:functions.main
    一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数
    若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件

    11.创建函数文件 可以不用#!/bin/bash “sherbang”机制
    函数文件示例:
    cat functions.main

    !/bin/bash

    functions.main

    findit()
    {
    if [ # -lt 1 ] ; then  echo “Usage:findit file”  return 1  fi  find / -name1 –print
    }

    12.载入函数
    函数文件已创建好后,要将它载入shell
    定位函数文件并载入shell的格式
    . filename 或 source filename
    注意:此即<点> <空格> <文件名>
    这里的文件名要带正确路径
    示例:
    上例中的函数,可使用如下命令:
    . functions.main

    13.检查载入函数
    使用set命令检查函数是否已载入。set命令将在shell中显示所有的载入函数
    示例:
    set
    findit=( )
    {
    if [ # -lt 1 ]; then  echo “usage :findit file”;  return 1  fi  find / -name1 -print
    }

    14.执行shell函数
    要执行函数,简单地键入函数名即可
    示例:
    findit groups
    /usr/bin/groups
    /usr/local/backups/groups.bak

    15.删除shell函数
    现在对函数做一些改动后,需要先删除函数,使其对shell不可用。使用unset命令完成删除函数
    命令格式为:
    unset function_name
    示例:
    unset findit
    再键入set命令,函数将不再显示
    环境函数
    使子进程也可使用
    声明:export -f function_name
    查看:export -f 或 declare -xf
    示例:
    在当前脚本调用functions文件里的func1 func2,传递给f1.sh,让f1.sh也可以调用该函数
    . functions
    declare -xf func1 func2
    func1 12
    ./f1.sh

    16.函数变量
    变量作用域:
    环境变量:当前shell和子shell有效
    本地变量(普通变量):只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数
    局部变量:函数的生命周期;函数结束时变量被自动销毁
    注意:如果函数中有局部变量,如果其名称同本地变量,使 用局部变量
    在函数中定义局部变量的方法
    local NAME=VALUE

    17.函数递归示例
    函数递归:
    函数直接或间接调用自身
    注意递归层数
    递归实例:
    阶乘是基斯顿·卡曼于 1808 年发明的运算符号,是数学术语
    一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且有0的阶乘为1,自然数n的阶乘写作n!
    n!=1×2×3×…×n
    阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n
    n!=n(n-1)(n-2)…1
    n(n-1)! = n(n-1)(n-2)!

    示例:
    fact.sh

    !/bin/bash

    #
    fact() {
    if [ 1eq0o1 -eq 1 ]; then
    echo 1
    else
    echo [1*(fact[1-1])]  fi  }  fact1

    18.fork炸弹
    fork炸弹是一种恶意程序,它的内部是一个不断在fork进程的无限循环,实质是一个简单的递归程序。由于程序是递归的,如果没有任何限制,这会导致这个简单的程序迅速耗尽系统里面的所有资源
    函数实现
    示例
    1. :(){ :|:& };:
    2. bomb() { bomb | bomb & }; bomb

    脚本实现
    cat Bomb.sh

    !/bin/bash

    ./0|./0&

    练习
    1.编写函数,实现OS的版本判断

    2.编写函数,实现取出当前系统eth0的IP地址

    3.编写函数,实现打印绿色OK和红色FAILED

    4.编写函数,实现判断是否无位置参数,如无参数,提示错误

    5.编写服务脚本/root/bin/testsrv.sh,完成如下要求
    (1) 脚本可接受参数:start, stop, restart, status
    (2) 如果参数非此四者之一,提示使用格式后报错退出
    (3) 如是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”
    考虑:如果事先已经启动过一次,该如何处理?
    (4) 如是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”
    考虑:如果事先已然停止过了,该如何处理?
    (5) 如是restart,则先stop, 再start
    考虑:如果本来没有start,如何处理?
    (6) 如是status, 则如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is running…”
    如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped…”
    其中:SCRIPT_NAME为当前脚本名
    (7)在所有模式下禁止启动该服务,可用chkconfig 和 service命令管理

    6.编写脚本/root/bin/copycmd.sh
    (1) 提示用户输入一个可执行命令名称
    (2) 获取此命令所依赖到的所有库文件列表
    (3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下
    如:/bin/bash ==> /mnt/sysroot/bin/bash
    /usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd
    (4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下: 如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
    (5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出

    7.编写函数实现两个数字做为参数,返回最大值

    8.斐波那契数列又称黄金分割数列,因数学家列昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2)
    利用函数,求n阶斐波那契数列

    9.汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘,利用函数,实现N片盘的汉诺塔的移动步骤

    19.信号捕捉trap
    trap ‘触发指令’ 信号
    自定义进程收到系统发出的指定信号后,将执行触发指令,而不会执行原操作
    trap ” 信号
    忽略信号的操作
    trap ‘-’ 信号
    恢复原信号的操作
    trap -p
    列出自定义信号操作

    trap示例

    !/bin/bash

    trap ‘echo “signal:SIGINT”’ int
    trap -p
    for((i=0;i<=10;i++))
    do
    sleep 1
    echo idonetrapinttrappfor((i=11;i<=20;i++))dosleep1echoi
    done
    trap ‘-’ int
    trap -p
    for((i=21;i<=30;i++))
    do
    sleep 1
    echo $i
    done


    1.数组
    变量:存储单个元素的内存空间
    数组:存储多个元素的连续的内存空间,相当于多个变量的集合
    数组名和索引
    索引(下标):编号从0开始,属于普通数组索引
    注意:索引可支持使用自定义的格式,而不仅是数值格式,即为关联数组索引,bash4.0版本之后开始支持
    bash的数组支持稀疏格式(索引不连续)
    声明数组:
    declare -a ARRAY_NAME
    declare -A ARRAY_NAME: 关联数组
    注意:两者不可相互转换

    2.数组赋值
    数组元素的赋值
    (1) 一次只赋值一个元素
    ARRAY_NAME[INDEX]=VALUE
    weekdays[0]=”Sunday”
    weekdays[4]=”Thursday”
    (2) 一次赋值全部元素
    ARRAY_NAME=(“VAL1” “VAL2” “VAL3” …)
    (3) 只赋值特定元素
    ARRAY_NAME=([0]=”VAL1” [3]=”VAL2” …)

    (4) 交互式数组值对赋值
    read -a ARRAY
    显示所有数组:declare -a
    只要能生成列表的方法都可以给数组赋值
    例如:
    1.digit=({1..10})
    echo ${digit[*]}
    2.alpha=(seq 10 20)

    3.引用数组
    引用数组元素:
    ARRAYNAME[INDEX][INDEX]0{ARRAY_NAME[*]}
    ARRAYNAME[@](){#ARRAY_NAME[*]}
    ${#ARRAY_NAME[@]}
    删除数组中的某元素:导致稀疏格式
    unset ARRAY[INDEX]
    删除整个数组:
    unset ARRAY

    示例:1.df.sh,当磁盘利用率大于5%的时候,显示报警 待完成

    4.数组数据处理
    引用数组中的元素:
    数组切片:ARRAY[@]:offset:numberoffset:number:{ARRAY[@]:offset}
    向数组中追加元素:
    ARRAY[${#ARRAY[*]}]=value
    关联数组:
    declare -A ARRAY_NAME
    ARRAY_NAME=([idx_name1]=’val1’ [idx_name2]=’val2‘…)
    注意:关联数组必须先声明再调用

    示例:1.rand.sh 十个随机数,比较最大和最小值,打印出来
    写法一老王思路:
    declare -a rand
    for ((i=0;i<10;i++));do
    rand[i]=RANDOM #第一个数即是最大值又是最小值
    if [ ieq0];thenmax={rand[i]}  min=max
    continue
    fi
    if [ “max"lt"rand[i]” ];then
    max=rand[$i]elif[min" -gt rand[$i]];thenmin={rand[i]}  else  true  fi  done  echo ALLrandom is &{rand[@]}  echo max=max
    echo min=$min

    写法二:
    生成10个随机数保存于数组中,并找出其最大值和最小值

    !/bin/bash

    declare -i min max
    declare -a nums
    for ((i=0;i<10;i++));do
    nums[i]=RANDOM
    [ i -eq 0 ] && min={nums[i]} && max={nums[i]}&& continue  [{nums[i]} -gtmax ] && max=nums[$i][{nums[i]} -ltmin ] && min=nums[$i]doneechoAllnumbersare{nums[*]}”
    echo Max is maxechoMinismin

    2.编写脚本,定义一个数组,数组中的元素是/var/log目录下所有以.log结尾的文件;统计出其下标为偶数的文件中的行数之和

    !/bin/bash

    #
    declare -a files
    files=(/var/log/*.log)
    declare -i lines=0
    for i in (seq0[{#files[*]}-1]); do  if [[iletlines+=(wc -l files[$i]|cutdf1)fidoneechoLines:lines.”

    练习
    输入若干个数值存入数组中,采用冒泡算法进行升序或降序排序
    将下图所示,实现转置矩阵matrix.sh
    1 2 3 1 4 7
    4 5 6 ===> 2 5 8
    7 8 9 3 6 9
    打印杨辉三角形

    5.字符串切片
    ${#var}:返回字符串变量var的长度

    var:offset:varoffsetoffsetoffset0{#var}-1 之间(bash4.2后,允许为负值)

    ${var:offset:number}:返回字符串变量var中从第offset个字符后(不包括第offset个字符)的字符开始,长度为number的部分

    ${var: -length}:取字符串的最右侧几个字符
    注意:冒号后必须有一空白

    ${var:offset:-length}:从最左侧跳过offset字符,一直向右取到距离最右侧lengh个字符之前的内容

    ${var: -length:-offset}:先从最右侧向左取到length个字符开始,再向右取到距离最右侧offset个字符之间的内容 -length > -offset ,倒取右边length,再从length里抛掉右侧offset,保留剩下的
    注意:-length前空格

    6.字符串处理
    基于模式取子串
    {var#*word}:其中word可以是指定的任意字符  功能:自左而右,查找var变量所存储的字符串中,第一次出现的word, 删除字符串开头至第一次出现word字符之间的所有字符{var##*word}:同上,贪婪模式,不同的是,删除的是字符串开头至最后一次由word指定的字符之间的所有内容,可以取基名
    示例:
    file=“var/log/messages”
    {file#*/}: log/messages{file##*/}: messages

    7.字符串处理
    {var%word*}:其中word可以是指定的任意字符  功能:自右而左,查找var变量所存储的字符串中,第一次出现的word, 删除字符串最后一个字符向左至第一次出现word字符之间的所有字符  file=”/var/log/messages”{file%/*}: /var/log
    ${var%%word*}:同上贪婪模式,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符;
    示例:
    url=http://www.magedu.com:80
    {url##*:} 80{url%%:*} http

    8.字符串处理-查找替换
    查找替换
    var/pattern/substrvarpatternsubstr{var//pattern/substr}: 贪婪模式 查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substr替换之
    {var/#pattern/substr}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substr替换之{var/%pattern/substr}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substr替换之

    9.字符串处理-查找删除–大小写转换
    查找并删除
    var/patternvarpattern{var//pattern}:删除var表示的字符串中所有被pattern匹配到的字符串
    {var/#pattern}:删除var表示的字符串中所有以pattern为行首匹配到的字符串{var/%pattern}:删除var所表示的字符串中所有以pattern为行尾所匹配到的字符串
    字符大小写转换
    {var^^}:把var中的所有小写字母转换为大写{var,,}:把var中的所有大写字母转换为小写

    10.变量赋值

    11.高级变量用法-有类型变量
    Shell变量一般是无类型的,但是bash Shell提供了declare和typeset两个命令用于指定变量的类型,两个命令是等价的
    declare [选项] 变量名
    -r 声明或显示只读变量
    -i 将变量定义为整型数
    -a 将变量定义为数组
    -A 将变量定义为关联数组
    -f 显示已定义的所有函数名及其内容
    -F 仅显示已定义的所有函数名
    -x 声明或显示环境变量和函数
    -l 声明变量为小写字母 declare –l var=UPPER
    -u 声明变量为大写字母 declare –u var=lower

    12.eval命令
    eval命令将会首先扫描命令行进行所有的先置换,然后再执行该命令。该命令适用于那些一次扫描无法实现其功能的变量.该命令对变量进行两次扫描
    示例:
    [root@server ~]# CMD=whoami
    [root@server ~]# echo CMD  whoami  [root@server ~]# evalCMD
    root
    [root@server ~]# n=10
    [root@server ~]# echo {0..n}    #echo 根本不执行n,只是置换变量值
    {0..10}
    [root@server ~]# eval echo {0..$n} #加上eval就不一样了,先替换再执行
    0 1 2 3 4 5 6 7 8 9 10

    13.间接变量引用
    如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用
    variable1的值是variable2,而variable2又是变量名,variable2的值为value,间接变量引用是指通过variable1获得变量值value的行为
    variable1=variable2
    variable2=value

    bash Shell提供了两种格式实现间接变量引用
    eval tempvar=$variable1tempvar={!variable1}
    示例:
    1.
    [root@server ~]# N=NAME
    [root@server ~]# NAME=wangxiaochun
    [root@server ~]# N1={!N}  [root@server ~]# echoN1
    wangxiaochun
    [root@server ~]# eval N2=$N  [root@server ~]# echoN2
    wangxiaochun

    2.
    title=ceo
    ceo=mage
    eval echo $titlemageecho{!title}

    14.创建临时文件
    mktemp命令:创建并显示临时文件,可避免冲突
    mktemp [OPTION]… [TEMPLATE]
    TEMPLATE: filenameXXX
    X至少要出现三个
    OPTION:
    -d: 创建临时目录
    -p DIR或–tmpdir=DIR:指明临时文件所存放目录位置
    示例:
    mktemp /tmp/testXXX
    tmpdir=mktemp –d /tmp/testdirXXX
    mktemp –tmpdir=/testdir testXXXXXX

    15.安装复制文件
    复制文件,如果目标文件夹没有可以自动创建,还可以改权限
    install命令:
    install [OPTION]… [-T] SOURCE DEST 单文件
    install [OPTION]… SOURCE… DIRECTORY
    install [OPTION]… -t DIRECTORY SOURCE…
    install [OPTION]… -d DIRECTORY…创建空目录
    选项:
    -m MODE,默认755
    -o OWNER
    -g GROUP
    示例:
    install -m 700 -o wang -g admins srcfile desfile
    install –m 770 –d /testdir/installdir

    16.expect介绍
    expect 是由Don Libes基于Tcl( Tool Command Language )语言开发的,主要应用于自动化交互式操作的场景,借助Expect处理交互的命令,可以将交互过程如:ssh登录,ftp登录等写在一个脚本上,使之自动化完成。尤其适用于需要对多台服务器执行相同操作的环境中,可以大大提高系统管理人员的工作效率

    expect命令
    expect 语法:
    expect [选项] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]
    选项
    -c:从命令行执行expect脚本,默认expect是交互地执行的
    示例:expect -c ‘expect “\n” {send “pressed enter\n”}
    -d:可以输出输出调试信息
    示例:expect -d ssh.exp

    expect中相关命令
    spawn:启动新的进程
    send:用于向进程发送字符串
    expect:从进程接受字符,捕获输入到感兴趣字符后,执行后边的命令
    interact:允许用户交互
    exp_continue 匹配多个字符串在执行动作后加此命令

    用法:
    expect最常用的语法(tcl语言:模式-动作)
    单一分支模式语法:
    expect “hi” {send “You said hi\n”}
    匹配到hi后,会输出“you said hi”,并换行
    多分支模式语法:
    expect “hi” { send “You said hi\n” } \
    “hehe” { send “Hehe yourself\n” } \
    “bye” { send “Good bye\n” }

    匹配hi,hello,bye任意字符串时,执行相应输出。等同如下:
    expect {
    “hi” { send “You said hi\n”}
    “hehe” { send “Hehe yourself\n”}
    “bye” { send “Good bye\n”}
    }

    示例
    1.远程登录scp传文件,全自动

    !/usr/bin/expect

    spawn scp /etc/fstab 192.168.8.100:/app
    expect {
    “yes/no” { send “yes\n”;exp_continue }
    “password” { send “magedu\n” }
    }
    expect eof

    2.远程登录,允许用户交互

    !/usr/bin/expect

    spawn ssh 192.168.8.100
    expect {
    “yes/no” { send “yes\n”;exp_continue }
    “password” { send “magedu\n” }
    }
    interact

    expect eof

    3.用变量表示IP

    !/usr/bin/expect

    set ip 192.168.8.100
    set user root
    set password magedu
    set timeout 10
    spawn ssh user@ip
    expect {
    “yes/no” { send “yes\n”;exp_continue }
    “password” { send “$password\n” }
    }
    interact

    4.把IP、用户名、密码变量做成数组

    !/usr/bin/expect

    set ip [lindex argv0]setuser[lindexargv 1]
    set password [lindex argv2]spawnsshuser@ip  expect {  “yes/no” { send “yes\n”;exp_continue }  “password” { send “password\n” }
    }
    interact

    ./ssh3.exp 192.168.8.100 root magedu

    5.执行多个命令

    !/usr/bin/expect

    set ip [lindex argv0]setuser[lindexargv 1]
    set password [lindex argv2]settimeout10spawnsshuser@ip  expect {  “yes/no” { send “yes\n”;exp_continue }  “password” { send “password\n” }
    }
    expect “]#” { send “useradd haha\n” }
    expect “]#” { send “echo magedu |passwd –stdin haha\n” }
    send “exit\n”
    expect eof

    ./ssh4.exp 192.168.8.100 root magedu

    6.:shell脚本调用expect

    !/bin/bash

    ip=1user=2
    password=$3
    expect <

    ./ssh5.sh 192.168.8.100 root magedu

    展开全文
  • 脚本编程之函数

    2019-12-22 23:32:14
    函数函数介绍定义函数函数使用函数返回值示例交互式定义脚本中定义函数使用函数文件载入函数和检查载入函数执行shell函数删除函数函数参数示例 函数介绍 函数function是由若干条shell命令组成的语句块,实现代码...

    函数介绍

    • 函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程
    • 它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell的一部分
    • 函数和shell比较类似,区别在于
      • shell程序在子shell中运行
      • 而shell函数在当前shell中运行,因此当前shell中,函数可以对shell中变量进行修改

    定义函数

    函数由函数名和函数体组成

    由以下几种方式命名:

    语法一:
    	function_name(){
    		函数体
    		}
    语法二:
    	function  f_name(){
    		函数体
    		}
    语法三:
    	function f_name{
    		函数体
    		}
    

    函数使用

    • 函数定义和使用
      • 可在交互式环境中定义
      • 可将函数放在脚本中作为它的一部分
      • 可放在只包含函数中的单独文件中
    • 函数调用:
      • 给定函数名
      • 函数名出现的地方会自动替换为函数体内的代码
    • 函数的生命周期
      • 被调用时创建,返回时终止

    函数返回值

    函数有两种返回值

    • 函数的执行结果返回值
      • 使用 echo等命令进行输出
      • 函数体中调用命令的输出结果
    • 函数退出的状态码
      • 默认取决于函数中执行的最后一条命令的退出状态码
      • 自定义退出状态码,格式为
        • return 从函数中返回,用最后的状态命令决定返回值
        • return 0 无错误
        • return 1-255 错误返回值

    示例

    交互式定义

    [root@localhost ~]# hello(){
    > echo "hello world"
    > }
    [root@localhost ~]# hello    #输入函数名,直接输出结果
    hello world
    [root@localhost ~]# unset hello   #取消函数
    
    

    脚本中定义函数

    函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用。

    [root@localhost ~]# cat func1
    #!/bin/bash
    # func1
    hello(){
    	echo "hello world"
    }
    hello
    
    

    使用函数文件

    • 可以将经常使用的函数存入函数文件,然后将函数文件载入shell
    • 文件名任意选取,但最好与相关任务有某种联系,如functions.main
    • 一旦函数文件载入shell,就可以在命令行中或者脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包括已经载入shell中的函数
    • 若要改动函数,首先用unset命令从shell中删除函数,改动完毕后,再重新载入文件

    示例:

    [root@localhost ~]# cat find_file 
    #!/bin/bash
    # function.main
    findit(){
    	if [ $# -lt 1 ];then
    		echo "please input a filename"
    		return 1
    	fi
    find / -name $1 -print
    }
    
    

    载入函数和检查载入函数

    • 函数文件定义好后,需要将它载入shell
    • 载入的语法为
      • . filename 或者 source filename
    • 使用set命令查看载入函数
    [root@localhost ~]# . find_file    # 载入之后在使用set
    [root@localhost ~]# set
    findit () 
    { 
        if [ $# -lt 1 ]; then
            echo "please input a filename";
            return 1;
        fi;
        find / -name $1 -print
    }
    
    
    

    执行shell函数

    执行shell函数,只需输入函数名即可

    [root@localhost ~]# findit groups
    /usr/bin/groups
    
    

    删除函数

    现在对函数做一些改动后,需要先删除函数,使其对shell不可用。使用unset命令完成函数删除

    • 命令格式:unset file_name
    • 环境函数
      • 声明:export -f function_name
      • 查看:export -f 或 declare -xf

    函数参数

    • 传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可;例如“testfunc arg1 arg2 …”
    • 在函数体中当中,可使用$1,$2, …调用这些参数;还可以使用$@, $*, $#等特殊变量

    示例

    编写脚本/root/bin/copycmd.sh
    (1) 提示用户输入一个可执行命令名称
    (2) 获取此命令所依赖到的所有库文件列表
    (3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下  
         如:/bin/bash ==> /mnt/sysroot/bin/bash
           /usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd
    (4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下:  如:/lib64/ld-linux-x86-64.so.2 ==>/mnt/sysroot/lib64/ld-linux-x86-64.so.2
    (5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出
    
     1 #!/bin/bash
      2 ldd_comm(){
      3         comm_where=`whereis $comm | cut -d ' '  -f2 | sed -rn 's/\/.*(\/.*\/.*)/\1/p'`
      4         declare -i index
      5         index=`ldd $comm_where | sed -rn 's/.*(\/.*\/.*[[:space:]]+).*/\1/p' | wc -l`
      6         declare -i j
      7         j=$[$index-1]
      8         declare -a cp_comm
      9         cp_comm=(`ldd $comm_where | sed -rn 's/.*(\/.*\/.*[[:space:]]+).*/\1/p'`)
     10         for  ((i=0;i<=$j;i++));do
     11                 cp ${cp_comm[$i]} /mnt/sysroot${cp_comm[$i]}
     12         done
     13 }
     14 
     15 while true;do
     16         read -p "please input a command or q(quit):" comm
     17         if `hash $comm &>/dev/null` ;then
     18                 ldd_comm
     19                 cp $comm_where /mnt/sysroot$comm_where
     20         else
    
    [root@localhost ~]# bash cpcmd.sh 
    please input a command or q(quit):mv
    please input a command or q(quit):cp
    please input a command or q(quit):ls
    please input a command or q(quit):djslakjdlksa
    wrong command , try agin
    please input a command or q(quit):q
    exited!
    [root@localhost sysroot]# ls bin/
    bash  cp  ls  mv
    
    
    
    
    展开全文
  • MATLAB 提供了一个强大的编程语言和交互式计算环境。我们可以在MATLAB 命令行中一次输入一个命令(两个大于号那里),也可以向某个.m文件写入一系列命令,按照执行任何 MATLAB 函数的相同方式来执行这些命令。 .m...

    MATLAB 提供了一个强大的编程语言和交互式计算环境。我们可以在MATLAB 命令行中一次输入一个命令(两个大于号那里),也可以向某个.m文件写入一系列命令,按照与执行任何 MATLAB 函数的相同方式来执行这些命令。

    .m文件分为两种:

    ——脚本,不接受输入参数或返回输出参数。它们处理工作区中的数据。

    ——函数,可接受输入参数,并返回输出参数。内部变量是函数的局部变量。

    虽然后缀一致,在电脑文件夹看不出区别,可在MATLAB目录里可以看出区别,带有fx的是函数文件,就是以function开头的文件。

    图片

    图片

    脚本文件通常我们初学会先接受脚本文件,因为它只是函数命令的集合,不涉及封装。如下所示。使用edit function1新建一个名为function1的.m文件,如果已有,将先打开这个文件。接着我们写简单代码运行这个文件,发现工作区出现了变量的名称和值。这代表了什么?这代表了这些变量被存储在了工作区空间中(可以理解为全局空间,任何函数和命令都可以直接调用这些变量),这说明,脚本文件是对全局空间进行操作的。既然如此,当然不会存在传入传出参数的问题,因为,往哪里传呢,都在这里了!

    图片

    图片

    函数文件下面看函数文件,功能和function1.m完全一致,为了和脚本文件对比,我设置的函数function2(这个名字也是.m文件的名字,它们两个必须一致。详细来说:函数文件的第一行必须是function开头的函数声明,然后函数名必须和文件名相同)没有任何参数(请注意,即便没有任何参数,小括号也不可以少!)我们运行一下,发现工作区没有变量出现,命令行的输出是分号不起作用的结果,我相信大家都明白什么意思,只是为了显示这个函数确实运行了。这是为什么?因为函数文件本身就创建了一个空间,所有的命令在函数的空间里运行,当然不会在代表全局空间的工作区中显示,这也就解释了函数文件必须要有输出参数的原因,否则接收不到运行结果!当然一些特殊函数,如clc,清屏,不需要任何输入输出除外!

    图片

        一个函数文件可以写多个函数吗?答案是肯定的,如下图:第二个子函数被成功调用!

    图片

        只要保证第一行的function与文件同名即可!因为刚刚说了一个函数文件就是一个独立的空间,所以定义在后面的子函数function2_sub是无法在外部被调用的,只可以被这个文件里的其他命令调用!

        看两个错误的例子,一个试图调用函数文件里的第二个函数,一个没有保证第一行函数与文件同名,都是错的!

    图片

    图片

        如果想要查看函数文件运行中内部变量的值,可以在数字右边单击,会出现小红点,代表断点,当函数运行到这一句时,会暂停,此时在工作区中看的的就是子函数里的所有变量,而全局变量此时是看不的!这也体现了函数文件的封装性。

    图片

    图片

    此外,补充一下匿名函数,有时候我们的函数短到没有必要写一个函数文件但又想多次调用时可采用。

    图片

    展开全文
  • LINUXSHELL编程

    2017-11-21 15:46:41
    交互式shell和非交互式shell的区别? A: shell脚本中指定使用的shell #!+指定的shell #(sharp)! (bang) #+! shebang 用户创建变量的约定: 全局变量可以被任何shell和从最初shell创建的其他...
  • Shell 编程基础(...)

    2020-03-31 15:26:01
    1、基础概念 Shell 程序一般被称为脚本(Script),是一组命令的集合,最简单的甚至可以单纯地堆砌命令,就像前文中提到的 ...个文件,故交互式 Shell执行脚本的 Shell本质上并无区别。只不过交互式运行的 Shell ...
  • aspasp.net的区别

    2010-11-09 19:45:45
    ASP(Active Server Pages)是Microsfot公司1996年11月推出的WEB应用程序开发技术,它既不是一种程序语言,也不是一种开发工具,而是一种技术框架,不须使用微软的产品就能编写它的代码,能产生和执行动态、交互式、...
  • 前 言 第1章 如何才能学好...第18章 Expect自动化交互式程序应用实践 / 317 第19章 企业Shell面试题及企业运维实战案例 / 340 第20章 子Shell及Shell嵌套模式知识应用 / 377 附 录 Linux重要命令汇总 / 393
  • Python编程入门经典

    热门讨论 2013-10-27 14:17:39
    1.1 编程与使用计算机的区别 3 1.1.1 编程的一致性 3 1.1.2 编程的可控性 4 1.1.3 程序要应对变化 4 1.1.4 小结 4 1.2 准备工作 4 1.2.1 在非Windows系统上安装 Python 3.1 5 1.2.2 使用Python Shell 5 1.3 开始使用...
  • 编程新手真言......

    2009-04-02 20:25:15
    shell编程交互式语句编程 232 Debug,编译期断言 232 图形原理之位图,图象和字体 233 为Windows说些好话 233 Minlearn Ruby (5) 网络原理P2P 234 Minlearn Ruby(4) 字符串WEB 234 加密解密 235 Minlearn(3)...
  • 电影一样,是一种综合艺术,并且是更高层次的综合艺术,它的出现代表了一种全新的娱乐方式——交互式娱乐(Interactive Entertainment)的诞生,而且从它的诞生到现在一直以其独特的魁力吸引了许多玩家,同时也激发...
  • 14.1.2 使用Access选项卡和使用ActiveX TabStrip控件的区别 436 14.2 ImageList控件详述 438 14.2.1 在设计阶段添加图像 438 14.2.2 在运行阶段向ImageList控件中添加图像 441 14.3 用ListView控件仿效...
  • 14.1.2 使用Access选项卡和使用ActiveX TabStrip控件的区别 436 14.2 ImageList控件详述 438 14.2.1 在设计阶段添加图像 438 14.2.2 在运行阶段向ImageList控件中添加图像 441 14.3 用ListView控件仿效Windows ...
  • Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐) 基本信息 原书名: Pro Oracle SQL 原出版社: Apress 作者: (美)Karen Morton Kerry Osborne Robyn Sands Riyaj Shamsudeen Jared Still 译者: 朱...
  • 该资料是《Oracle SQL高级编程》的源代码 对应的书籍资料见: Oracle SQL高级编程(资深Oracle专家力作,OakTable团队推荐) 基本信息 原书名: Pro Oracle SQL 原出版社: Apress 作者: (美)Karen Morton Kerry ...
  • ACReport中国报表控件2011(Ver2.42)

    热门讨论 2011-03-06 00:03:30
    9. 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。 10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得报表...
  • 9. 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。 10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得报表...
  • 9. 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。 10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得报表...
  • 9. 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。 10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得...
  • 9. 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。 10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得报表...
  • 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。  10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得报表...
  • 9. 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。 10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得报表...
  • 9. 支持脚本和窗体编程,报表设计人员可以编写脚本、在报表设计器里为报表添加窗体,为最终用户提供更丰富的交互功能。 10. 既可以使用应用程序中的数据集,也支持在报表中直接连接各种数据库,通过SQL直接获得报表...
  • python 学习 第一天

    2017-11-18 14:42:46
    python 学习 第一天首先... 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编写代码。 神奇 运行的快捷键 shift+F10 学习 Python 其他语言最大的区别就是,Python 的代码块不使用大括号 {}
  • javascript基础

    2016-07-23 19:36:00
    javascript学习笔记 简介 javascript是什么? JavaScript是一种运行在浏览器中的解释型、面向对象、事件驱动编程语言。 javascript能干什么?...javascriptECMAScript的区别? ECMAScript是一种...
  • C#.NET3.5高级程序设计第四版高清PDF中文完整版

    千次下载 热门讨论 2011-07-05 10:25:50
    1.9 程序集/命名空间/类型的区别  1.10 使用ildasm.exe探索程序集  1.11 使用lutz roeder的reflector来查看程序集  1.12 部署.net运行库  1.13 net的平台无关性  1.14 小结  第2章 构建c#应用程序  ...
  • 本节主要内容Scala 基础语法第一个 Scala 程序交互式编程脚本形式基本语法 Scala 基础语法 如果你之前是一名 Java 程序员,并了解 Java 语言的基础知识,那么你能很快学会 Scala 的基础语法。 Scala Java 的最大...
  • Scala学习(一)

    2021-03-02 11:16:53
    Scala基础语法 ScalaJava的最大区别是:Scala语句末尾的分号是可选的 我们可以认为Scala程序是对象的集合,通过调用彼此的方法来实现消息...交互式编程 脚本形式 创建一个HelloWorld.scala的文件来执行代码 objec
  • PHPMySQL.WEB开发

    2013-04-01 17:18:52
    本书介绍了如何使用这些工具创建高效和交互式的Web应用。它清晰地介绍了PHP语言的基础,解释了如何设置和使用MySQL数据,以及如何使用PHP数据库和服务器进行交互。 本书非常实用,包括大量实际应用中的例子。例如...
  • 1.9 程序集/命名空间/类型的区别  1.10 使用ildasm.exe探索程序集  1.11 使用Lutz Roeder的Reflector来查看程序集  1.12 部署.NET运行库  1.13 NET的平台无关性  1.14 小结  第2章 构建C#应用程序  ...

空空如也

空空如也

1 2 3 4
收藏数 69
精华内容 27
关键字:

交互式编程与脚本式编程区别