|簡體中文

比思論壇

 找回密碼
 按這成為會員
搜索



查看: 3155|回復: 12
打印 上一主題 下一主題

各种Shell的介绍

[複製鏈接]

25

主題

0

好友

144

積分

小學生

Rank: 2

  • TA的每日心情

    2015-9-9 16:11
  • 簽到天數: 1 天

    [LV.1]初來乍到

    推廣值
    0
    貢獻值
    0
    金錢
    1739
    威望
    144
    主題
    25
    樓主
    發表於 2015-9-9 16:49:13
    Shell


    在DOS 中,你可能会从事一些例行的重覆性工作,此时你会将这些重覆性的命令写成批次档,只要执行这个批次档就等於执行这些命令。大家会问在UNIX中是否有批次处 理这个东东,答案是有的。在UNIX中不只有如DOS 的批次处理,它的功能比起DOS 更强 大,相对地也较复杂,已经和一般的高阶语言不相上下。在UNIX中大家都不叫做批次档 ,而叫做Shell Script。

    一般而言,Shell Script的地位和其它的可执行档(或命令)是完全相同的,只不过Shell Script是以文字档的方式储存,而非二进位档。而执行Shell Script时,必须有一个程式将其内容转成一道道的命令执行,而这个程式其实就是Shell ,这也就是为 什麽我们叫做Shell Script的原因(往後我们称为Script)。不同Shell 的Script基本 上会有一些差异,所以我们不能将写给A shell 的Script用B shell 执行。而在UNIX中 大家最常使用Bourne Shell以及C Shell ,所以这堂课就介绍这两种Script的写法。

    □将文字档设为可执行的Shell Script

    如果我们已经写好Script,如何将其设成可执行档呢?因为Script其实是一个可执 行档,所以必须将其存取权设定成可执行。我们可以使用下列命令更改存取权:

    chmod u+x filename 只有自己可以执行,其它人不能执行

    chmod ug+x filename 只有自己以及同一群可以执行,其它人不能执行

    chmod +x filename 所有人都可以执行

    而我们如何指定使用那一个Shell 来解释所写的Script呢?几种基本的指定方式如 下所述:

    1. 如果Script的第一个非空白字元不是"#",则它会使用Bourne Shell。

    2. 如果Script的第一个非空白字元是"#"时,但不以"#!"开头时,则它会使用C Shell。

    3. 如果Script以"#!"开头,则"#!"後面所写的就是所使用的Shell,而且要将整个路径名称指出来。这里建议使用第三种方式指定Shell ,以确保所执行的就是所要的。Bourne Shell的路 径名称为/bin/sh ,而C Shell 则为/bin/csh。

    除了在Script内指定所使用的Shell 外,你也可以在命令列中强制指定。比如你要 用C Shell 执行某个Script,你可以下这个命令:

    csh filename

    此时的Script的存取权就不一定要为可执行档,其内部所指定的Shell 也会无效,详细 的情形後面会讨论。

    □Script 的基本结构及观念 Script是以行为单位,我们所写的Script会被分解成一行一行来执行。而每一行可以是命令、注解、或是流程控制指令等。如果某一行尚未完成,可以在行末加上"\" , 这个时候下一行的内容就会接到这一行的後面,成为同一行,如下

    echo the message is

    too long so we have

    to split it into

    several lines.

    当Script中出现"#" 时,再它後面的同一行文字即为注解,Shell 不会对其翻译。

    在Script中要执行一个命令的方法和在命令列中一样,你可以前景或背景执行,执 行命令时也会需要设定一些环境变数。

    Script的流程控制和一般高阶语言的流程控制没有什麽两样,也和高阶语言一样有 副程式。这些使得Script的功能更加强大。

    为了达到与高阶语言相同的效果,我们也可以在Script中设定变数,如此使Script 成为一个名付其实的高阶语言。

    □Bourne Shell

    一、变数

    Bourne Shell的变数型态只有字串变数,所以要使用数值运算则必须靠外部命令达 成目的。而其变数种类有下列几种:

    1. 使用者变数 这是最常使用的变数,我们可以任何不包含空白字元的字串来当做变数名称。 设定变数值时则用下列方式:

    var=string 取用变数时则在变数名称前加上一"$" 号。

    name=Tom

    echo name

    echo $name

    结果如下:

    name

    Tom

    2. 系统变数(环境变数)

    和使用者变数相似,只不过此种变数会将其值传给其所执行的命令。要将一使 用者变数设定为系统变数,只要加上:

    export var

    name=Tom

    export name

    以下是使用者一进入系统之後就已设定好的系统变数:

    $HOME 使用者自己的目录

    $PATH 执行命令时所搜寻的目录

    $TZ 时区

    $MAILCHECK 每隔多少秒检查是否有新的信件

    $PS1 在命令列时的提示号

    $PS2 当命令尚未打完时,Shell 要求再输入时的提示号

    $MANPATH man 指令的搜寻路径

    3. 唯读的使用者变数

    和使用者变数相似,只不过这些变数不能被改变。要将使用者变数设成唯读的 ,只要加上:

    readonly var 而若只打readonly则会列出所有唯读的变数.还有一点,系统变数不可以设定 成唯读的。

    name=Tom

    readonly name

    echo $name

    name=John

    readonly

    结果如下: Tom name: is read only readonly name readonly ......

    4. 特殊变数

    有些变数是一开始执行Script时就会设定,并且不以加以修改,但我们不叫它 唯读的系统变数,而叫它特殊变数(有些书会叫它唯读的系统变数),因为这 些变数是一执行程式时就有了,况且使用者无法将一般的系统变数设定成唯读 的。以下是一些等殊变数:

    $0 这个程式的执行名字

    $n 这个程式的第n个参数值,n=1..9 $* 这个程式的所有参数

    $# 这个程式的参数个数

    $$ 这个程式的PID $! 执行上一个背景指令的PID

    $? 执行上一个指令的返回值

    当你执行这个程式时的参数数目超过9 个时,我们可以使用shift 命令将参数 往前移一格,如此即可使用第10个以後的参数。除此之外,吾人可以用set 命 令改变$n及$*,方法如下:

    set string 如此$*的值即为string,而分解後则会放入$n。如果set 命令後面没有参数, 则会列出所有已经设定的变数以及其值。

    档名:ex1 参数:this is a test

    echo Filename: $0

    echo Arguments: $*

    echo No. of args.: $#

    echo 2nd arg.: $2

    shift

    echo No. of args.: $#

    echo 2nd arg.: $2

    set hello, everyone

    echo Arguments: $*

    echo 2nd arg.: $2

    结果如下:

    Filename: ex1

    Arguments: this is a test No. of args.: 4

    2nd arg.: is

    No. of args.: 3

    2nd arg.: a

    Arguments: hello, everyone

    2nd arg.: everyone

    值得一提的是,当你想从键盘输入一变数值时,你可以使用下面的命令:

    read var1 var2..... 这时read会将一个字分给一个变数。如果输入的字比变数还多,最後一个变数会将剩下的字当成其值。如果输入的字比变数还少,则後面的变数会设成空字串。 如果需要处理数值运算,我们可以使用expr命令。其参数及输出列於附录A。

    二、执行命令

    在Bourne Shell中有五种方法执行一个命令,而这五种方式所产生的果有些许的不 同。

    1. 直接下命令 这个方式和在命令列中直接下命令的效果一样。

    2. 使用sh命令 sh command 这个档案必须是Bourne Shell的Script,但这个档案并不一定要设成可执行。 除此之外和直接下命令的方式一样。

    3. 使用"."命令 . command 这时和使用sh命令相似,只不过它不像sh一般会产生新的process ,相反地, 它会在原有的process 下完成工作。

    4. 使用exec命令 exec command 此时这个Script将会被所执行的命令所取代。当这个命令执行完毕之後,这个 Script也会随之结束。

    5. 使用命令替换 这是一个相当有用的方法。如果想要使某个命令的输出成为另一个命令的参数 时,就一定要使用这个方法。我们将命令列於两个"`" 号之间,而Shell 会以 这个命令执行後的输出结果代替这个命令以及两个"`" 符号。

    str='Current directory is '`pwd` echo $str

    结果如下:

    Current directory is /users/cc/mgtsai

    这个意思是pwd 这个命令输出"/users/cc/mgtsai",而後整个字串代替原 来的`pwd` 设定str 变数,所以str 变数的内容则会有pwd 命令的输出。

    number=`expr $number + 1` 这就是先前所提要作数值运算的方法,基本上expr命令只将运算式解,而後输出到标准输出上。如果要将某变数设定成其值,非得靠命令替换的方 式不可。这个例子是将number变数的值加1 後再存回number变数。

    三、流程控制 在介绍流程控制之前,我们先来看看test命令。test命令的参数是条件判断式,当 条件为真时则传回非零值,而条件为伪时则传回零。在所有的流程控制都必须用到 test命令来判断真伪。而test命令的使用方法则列於附录B。

    test $# = 0 如果执行这个程式没有参数时,会传回非零值代表"$# = 0"这个条件成立。反 之则会传回零。

    以下介绍各种流程控制:

    1. if then 语法以及流程图如下 语法以及流程图如下

    if(condition)

    then

    then-commands

    fi

    condition 是一个test命令。往後所介绍的各种流程中的condition 都是test 命令。

    档名:chkarg

    if(test$#!=0)

    then

    echo Arg1:$1

    fi

    $ chkarg Hello

    Arg1: Hello

    $ chkarg $

    2. if then else 语法以及流程图如下

    if(condition)

    then

    then-commands

    else

    else-commands

    fi

    3. if then elif 语法以及流程图如下

    if(condition1)

    then

    commands1

    elif(condition2)

    then

    commands2

    else

    commands3

    fi

    echo 'word 1: \c'

    read word1

    echo 'word 2: \c'

    read word2

    echo 'word 3: \c'

    read word3

    if (test "$word1" = "$word2" -a "$word2" = "$word3")

    then

    echo 'Match: words 1, 2, & 3'

    elif (test "$word1" = "$word2")

    then

    echo 'Match: words 1 & 2'

    elif (test "$word1" = "$word3")

    then echo 'Match: words 1 & 3'

    elif (test "$word2" = "$word3")

    then

    echo 'Match: words 2 & 3'

    else

    echo 'No match'

    fi

    4. for in 语法以及流程图如下

    for var in arg-list

    do

    commands

    done

    for a in xx yy zz

    do

    echo $a

    done

    结果如下:

    xx yy yy zz

    5. for 语法以及流程图如下

    for var

    do commands

    done

    档名:lstarg

    for a

    do

    echo $a

    done

    $lstarg xx yy zz

    xx yy yy zz

    6. while 语法以及流程图如下

    while (condition)

    do

    commands

    done

    number=0

    while (test $number -lt 10)

    do

    echo "$number\c"

    number=`expr $number + 1`

    done

    echo

    结果如下: 0123456789

    7. until 语法以及流程图如下

    until (condition)

    do

    commands

    done

    它和while 的不同只在於while 是在条件为真时执行回圈,而until 是在条件 为假时执行回圈。

    8. break及continue 这两者是用於for, while, until 等回圈控制下。break 会跳至done後方执行 ,而continue会跳至done执行,继续执行回圈。

    9. case 语法以及流程图如下

    case str in

    pat1) commands1;;

    pat2) commands2;;

    pat3) commands3;;

    esac

    而pat 除了可以指定一些确定的字串,也可以指定字串的集合,如下

    * 任意字串

    ? 任意字元

    [abc] a, b, 或c三字元其中之一

    [a-n] 从a到n的任一字元

    | 多重选择

    echo 'Enter A, B, or C: \c'

    read letter

    case $letter in

    A|a) echo 'You entered A.';;

    B|b) echo 'You entered B.';;

    C|c) echo 'You entered C.';;

    *) echo 'Not A, B, or C';;

    esac

    10. 函数 格式如下 function-name() { commands } 而要呼叫此函数,就像在命令列下直接下命令一般。

    □C Shell C Shell 有些特性和Bourne Shell一样,但有些不相同。这里介绍与Bourne Shell 不相同的地方。

    一、变数

    1. 字串变数 这个部分和Bourne Shell的变数一样,只不过在设定变数值时不能使用Bourne Shell的方式,而必须打:

    set var=value

    2. 数字运算 基本上C Shell 没有数字变数,但C Shell 却有简单的方法处理数字运算:

    @ var operator expression

    operator可以是C 语言中的=, +=, -=,......,而expression则是运算式。运 算式的运算子如下:

    A. () 改变计算的顺序 ~@

    B. ~ 位元NOT运算 @~~ ! 逻辑否定

    C. % 取馀数 C. % 取馀数 / 除 * 乘 - 减 + 加

    D. >> 右移 << 左移

    E. > 大於 < 小於 >= 大於等於 <= 小於等於 != 不等於 == 等於

    F. & 位元AND运算 ^ 位元XOR运算 | 位元OR 运算

    G. && 逻辑AND || 逻辑OR

    除此之外,我们也可以检验一个档案的状态,如下

    -n filename

    而-n可为下列之一

    -d 档案是一个目录档案

    -e 档案存在

    -f 档案为一般的档案

    -o 使用者拥有这个档案

    -r 使用者可以读取这个档案

    -w 使用者可以写入这个档案

    -x 使用者可以执行这个档案

    -z 档案长度为0

    @ count = count + 1

    @ flag = -e /users/cc/mgtsai/mail && -e /usr/spool/mail

    3. 阵列

    在C Shell 中,我们可以宣告阵列变数,方式如下

    set var=(val1 val2 ......) 而var[1]之值为val1,var[2]之值为val2......。而$var代表整个阵列。我们 可以用$#var 来计算阵列个数,也可以用$?var 来检查某个变数是否已宣告。

    4. 特殊变数

    $argv 和Bourne Shell的$*相似,只不过这是一个阵列。

    $argv[n] 和Bourne Shell的$n相同,但不受个数限制。

    $#argv 和Bourne Shell的$#相同

    $home 和Bourne Shell的$HOME相同

    $path 和Bourne Shell的$PATH相似,只不过这是一个阵列

    $prompt 和Bourne Shell的$PS1相同

    $shell Shell的路径名称 $status 和Bourne Shell的$?相同

    $$ 和Bourne Shell的$$相同

    $< 键盘输入

    二、执行命令

    基本上和Bourne Shell相同,只有一点在Bourne Shell中的"." 命令在C Shell 中 则为"source"命令。

    三、流程控制

    在C Shell 中流程控制不像Bourne Shell中一般需要使用test命令。相反地,它和 C 语言类似只要在条件中写出运□式即可。当运算结果不为零时,其值为真,为零 时其值为伪。以下是C Shell的流程控制

    1. if 语法如下

    if (expression) simple-command

    2. goto 语法如下

    goto label

    这时程式会跳至以l"label:"开头的那一行执行

    if ($#argv == 2) goto goodargs

    echo 'Please use two arguments.'

    exit

    goodrags: ...

    3. if then else

    这和Bourne Shell的if then, if then else, if then elif 相似。语法如下

    A. if (expression) then commands endif

    B. if (expression) then commands else commands endif

    C. if (expression) then commands else if (expression) then commands else commands endif

    4. foreach 这和Bourne Shell的for in相似。语法如下

    foreach var (arg-list)

    commands

    end

    5. while 这和Bourne Shell的while相似。语法如下

    while (expression)

    commands

    end

    6. break及continue

    这和Bourne Shell的break 及continue相似,是用来中断foreach 及while 回 圈。

    7. switch 这和Bourne Shell的case相似。语法如下

    switch (string)

    case pat1:

    commands1

    breaksw

    case pat2:

    commands2

    breaksw

    case pat3:

    commands3

    breaksw

    endsw

    □附录A expr命令

    命令格式

    expr expression

    叙述

    expression是由字串以及运算子所组成,每个字串或是运算子之间必须用空白隔开 。下表是运算子的种类及功能,而优先顺序则以先後次序排列,我们可以利用小括 号来改变运算的优先次序。其运算结果则输出至标准输出上。

    : 字串比较。比较的方式是以两字串的第一个字母开始,而以第二个字串的 字母结束。如果相同时,则输出第二个字串的字母个数,如果不同时则传 回0 。

    * 乘法

    / 除法

    % 取馀数

    + 加法

    - 减法

    < 小於

    <= 小於等於

    = 等於

    != 不等於

    >= 大於等於

    > 大於

    & AND运算

    | OR运算

    当expression中含有"*", "(", ")" 等符号时,必须在其前面加上"\" ,以免被 Shell 解释成其它意义。

    expr 2 \* \( 3 + 4 \) 其输出为14

    □附录B test命令

    命令格式

    test expression

    叙述

    expression 中包含一个以上的判断准则以作为test评诂的标准。两准则间用"-a"代 表逻辑AND 运算,"-o"代表逻辑OR运算,而在准则前放置一"!" 代表NOT 运算。如 果没有括号,则优先权则为"!" > "-a" > "-o" 。和expr命令相同,相使用左右括号时,必须在其前面加上"\" 。以下是有关准则的叙述(合叙述时传回真,否则传 回伪):

    string string不为空白字串

    -n string string的长度大於0

    -z string string的长度等於0

    string1=string2 string1等於string2

    string1!=string2 string1不等於string2

    int1 -gt int2 int1大於int2

    int1 -ge int2 int1大於等於int2

    int1 -eq int2 int1等於int2

    int1 -ne int2 int1不等於int2

    int1 -le int2 int1小於等於int2

    int1 -lt int2 int1小於int2

    -r filename 档案可读取

    -w filename 档案可写入

    -x filename 档案可执行

    -f filename 档案为一般档

    -d filename 档案为目录

    -s filename 档案为非空的一般档

    test -r "$filename" -a -s "$filename"






    無效樓層,該帖已經被刪除

    0

    主題

    0

    好友

    385

    積分

    中學生

    Rank: 3Rank: 3

  • TA的每日心情
    擦汗
    7 天前
  • 簽到天數: 215 天

    [LV.7]常住居民III

    推廣值
    0
    貢獻值
    0
    金錢
    1359
    威望
    385
    主題
    0
    板凳
    發表於 2016-1-5 16:09:27
    太详细了,学习
    無效樓層,該帖已經被刪除
    5#
    無效樓層,該帖已經被刪除
    6#
    無效樓層,該帖已經被刪除

    0

    主題

    0

    好友

    112

    積分

    小學生

    Rank: 2

  • TA的每日心情
    無聊
    2024-6-18 20:23
  • 簽到天數: 81 天

    [LV.6]常住居民II

    推廣值
    0
    貢獻值
    0
    金錢
    669
    威望
    112
    主題
    0
    7#
    發表於 2016-3-25 14:41:03
    先赞一个
    8#
    無效樓層,該帖已經被刪除

    4

    主題

    0

    好友

    749

    積分

    高中生

    Rank: 4

  • TA的每日心情
    擦汗
    2024-10-28 11:19
  • 簽到天數: 1067 天

    [LV.10]以壇為家III

    推廣值
    0
    貢獻值
    15
    金錢
    270
    威望
    749
    主題
    4

    簽到勳章 簽到達人 文明人 回文勇士

    9#
    發表於 2016-5-13 21:21:18
    用得最多还是bash

    49

    主題

    0

    好友

    181

    積分

    小學生

    Rank: 2

  • TA的每日心情
    擦汗
    2022-4-21 21:16
  • 簽到天數: 101 天

    [LV.6]常住居民II

    推廣值
    0
    貢獻值
    0
    金錢
    533
    威望
    181
    主題
    49
    10#
    發表於 2016-5-27 08:44:09
    楼主的机智帅气深深打动了我
    重要聲明:本論壇是以即時上載留言的方式運作,比思論壇對所有留言的真實性、完整性及立場等,不負任何法律責任。而一切留言之言論只代表留言者個人意見,並非本網站之立場,讀者及用戶不應信賴內容,並應自行判斷內容之真實性。於有關情形下,讀者及用戶應尋求專業意見(如涉及醫療、法律或投資等問題)。 由於本論壇受到「即時上載留言」運作方式所規限,故不能完全監察所有留言,若讀者及用戶發現有留言出現問題,請聯絡我們比思論壇有權刪除任何留言及拒絕任何人士上載留言 (刪除前或不會作事先警告及通知 ),同時亦有不刪除留言的權利,如有任何爭議,管理員擁有最終的詮釋權。用戶切勿撰寫粗言穢語、誹謗、渲染色情暴力或人身攻擊的言論,敬請自律。本網站保留一切法律權利。

    手機版| 廣告聯繫

    GMT+8, 2024-11-5 18:35 , Processed in 0.022745 second(s), 27 queries , Gzip On.

    Powered by Discuz! X2.5

    © 2001-2012 Comsenz Inc.

    回頂部