Shell基本语法及示例

Shell的运行

使用文件头

加入文件头#!/bin/bash

$ chmod +x $script_name

$ ./$script_name

Sh命令

$ sh $script_name

注:运行失败提示找不到文件时,请检查文件格式是否是UNIX格式,可通过notepad++中

编辑->文档格式转换改变文档格式,或者使用vi编辑器中的set ff=unix命令

 

脚本传参

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,$0 为执行的文件名,$1 为执行脚本的第一个参数,$2 为执行脚本的第二个参数,以此类推……

 

参数

说明

$#

传递到脚本的参数个数

$*

以一个单字符串显示所有向脚本传递的参数。
如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。

$$

脚本运行的当前进程ID号

$!

后台运行的最后一个进程的ID号

$@

与$*相同,但是使用时加引号,并在引号中返回每个参数。
如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。

$-

显示Shell使用的当前选项,与set命令功能相同。

$?

显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

脚本内容:

echo "Shell 传递参数实例!";

echo "第一个参数为:$1";

echo "参数个数为:$#";

echo "传递的参数作为一个字符串显示:$*";

echo "-- \$* 演示 ---"

for i in "$*"; do

    echo $i

done

echo "-- \$@ 演示 ---"

for i in "$@"; do

    echo $i

done

输出:

Shell 传递参数实例!

脚本路径为:./test.sh

第一个参数为:1

参数个数为:4

传递的参数作为一个字符串显示:1 2 3 4

-- $* 演示 ---

1 2 3 4

-- $@ 演示 ---

1

2

3

4

输出重定向

大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回​​到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。

重定向命令列表如下:

 

命令

说明

command > file

将输出重定向到 file。

command < file

将输入重定向到 file。

command >> file

将输出以追加的方式重定向到 file。

n > file

将文件描述符为 n 的文件重定向到 file。

n >> file

将文件描述符为 n 的文件以追加的方式重定向到 file。

n >& m

将输出文件 m 和 n 合并。

n <& m

将输入文件 m 和 n 合并。

<< tag

将开始标记 tag 和结束标记 tag 之间的内容作为输入。

注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。

 

/dev/null 文件

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。

 

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

$ command > /dev/null

 

如果希望屏蔽同时 stdout 和 stderr,可以这样写:

$ command > /dev/null 2>&1

变量、数组和字符串

声明

变量名和等号之间不能有空格,命名须遵循如下规则:

  1. 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  2. 中间不能有空格,可以使用下划线(_)。
  3. 不能使用标点符号。
  4. 不能使用bash里的关键字(可用help命令查看保留关键字)。

有效的变量名:

RUNOOB

LD_LIBRARY_PATH

_var

var2

直接在for循环中声明:

for file in `ls /etc`

for file in $(ls /etc)

引用

${var_name} 或 $var_name

强烈建议只使用前一种方式,避免出错

字符串

可使用单引号和双引号表示,但需要注意自个的区别:

  1. 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
  2. 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。
  3. 双引号里可以有变量
  4. 双引号里可以出现转义字符

拼接字符串

your_name="runoob"# 使用双引号拼接

greeting="hello, "$your_name" !"

greeting_1="hello, ${your_name} !"

echo $greeting  $greeting_1# 使用单引号拼接

greeting_2='hello, '$your_name' !'

greeting_3='hello, ${your_name} !'

echo $greeting_2  $greeting_3

 

输出

hello, runoob ! hello, runoob !

hello, runoob ! hello, ${your_name} !

获取字符串长度

string="abcd"

echo ${#string} #输出 4

 

查找子字符串

string="runoob is a great site"

echo `expr index "$string" io`  # 输出 4 #

查找字符i或 o的位置(哪个字母先出现就计算哪个)

 

字符串提取

假设有变量 var=http://www.aaa.com/123.htm.

  1. # 号截取,删除左边字符,保留右边字符。

echo ${var#*//}

其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符

即删除 http://

结果是 www.aaa.com/123.htm

 

  1. ## 号截取,删除左边字符,保留右边字符。

echo ${var##*/}

##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符

即删除 http://www.aaa.com/

结果是 123.htm

 

  1. %号截取,删除右边字符,保留左边字符

echo ${var%/*}

%/* 表示从右边开始,删除第一个 / 号及右边的字符

结果是:http://www.aaa.com

 

  1. %% 号截取,删除右边字符,保留左边字符

echo ${var%%/*}

 %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符

结果是:http:

 

  1. 从左边第几个字符开始,及字符的个数

echo ${var:0:5}

其中的 0 表示左边第一个字符开始,5 表示字符的总个数。

结果是:http:

 

  1. 从左边第几个字符开始,一直到结束。

echo ${var:7}

其中的 7 表示左边第8个字符开始,一直到结束。

结果是 www.aaa.com/123.htm

 

  1. 从右边第几个字符开始,及字符的个数

echo ${var:0-7:3}

其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。

结果是:123

 

  1. 从右边第几个字符开始,一直到结束。

echo ${var:0-7}

表示从右边第七个字符开始,一直到结束。

结果是:123.htm

 

注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

 

 

数组

定义

my_array=(A B C D)

或通过索引定义

array_name[0]=value0

array_name[1]=value1

array_name[2]=value2

array_name[3]=value2

数组遍历

索引遍历

echo "第一个元素为: ${my_array[0]}"

echo "第二个元素为: ${my_array[1]}"

echo "第三个元素为: ${my_array[2]}"

echo "第四个元素为: ${my_array[3]}"

全部元素

echo "数组的元素为: ${my_array[*]}"

echo "数组的元素为: ${my_array[@]}"

获取数组长度

echo "数组元素个数为: ${#my_array[*]}"

echo "数组元素个数为: ${#my_array[@]}"

条件判断

数值测试

参数

说明

-eq

等于则为真

-ne

不等于则为真

-gt

大于则为真

-ge

大于等于则为真

-lt

小于则为真

-le

小于等于则为真

 

字符串测试

参数

说明

=

等于则为真

!=

不相等则为真

-z 字符串

字符串的长度为零则为真

-n 字符串

字符串的长度不为零则为真

 

文件测试

参数

说明

-e 文件名

如果文件存在则为真

-r 文件名

如果文件存在且可读则为真

-w 文件名

如果文件存在且可写则为真

-x 文件名

如果文件存在且可执行则为真

-s 文件名

如果文件存在且至少有一个字符则为真

-d 文件名

如果文件存在且为目录则为真

-f 文件名

如果文件存在且为普通文件则为真

-c 文件名

如果文件存在且为字符型特殊文件则为真

-b 文件名

如果文件存在且为块特殊文件则为真

注:此类条件表达式固定写法必须使用中括号,且各项中间必须有空格

num1=100

num2=100

if [ $[num1] -eq $[num2] ] ;then

echo '两个数相等!'

else

echo '两个数不相等!'

fi

num1="ru1noob"

num2="runoob"

if [ $num1 = $num2 ] ;then

    echo '两个字符串相等!'

else

    echo '两个字符串不相等!'

fi

if [ -e /bin/bash ] ;then

    echo '文件已存在!'

else

    echo '文件不存在!'

fi

 

多重判断

if [ condition1 ] ;then

    echo 1

elif [ condition1 ] ;then

    echo 2

else

    echo 3

fi

 

多重条件表达式

[ condition1 ] || [ condition2 ]

[ condition1 ] && [ condition2 ]

 

循环

For循环

for num in 1 2 3 4 5

do

    echo "The value is: $num"

done

 

for i in $(seq 1 5)

do

    echo ${i}

done

 

my_array=(A B C D)

for item in ${my_array[@]}

do

echo ${item}

done

 

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

do

  echo ${i}

done

 

While循环

int=1

while(( $int<=5 ))

do

    echo $int

    let "int++"

done

 

使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量,具体可查阅:http://www.runoob.com/linux/linux-comm-let.html

 

Case、循环控制

while :

do

    echo -n "输入 1 到 5 之间的数字: "

    read aNum

    case $aNum in

        1|2|3) echo "你输入的数字为 $aNum!"

        ;;

        4)  echo '你输入了 4'

            continue

        ;;

        5)  echo '你输入了 5'

        ;;

        *)  echo "你输入的数字不是 1 到 5 之间的!"

            break

        ;;

    esac

done

 

 

 

 

 

 

函数

定义

注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。

函数返回值在调用该函数后通过 $? 来获得

 

funWithReturn(){

    echo "这个函数会对输入的两个数字进行相加运算..."

    echo "输入第一个数字: "

    read aNum

    echo "输入第二个数字: "

    read anotherNum

    echo "两个数字分别为 $aNum 和 $anotherNum !"

    return $(($aNum+$anotherNum))}

funWithReturn

echo "输入的两个数字之和为 $? !"

 

输出类似下面:

 

这个函数会对输入的两个数字进行相加运算...

输入第一个数字:

1

输入第二个数字:

2

两个数字分别为 1 和 2 !

输入的两个数字之和为 3 !

 

传参

funWithParam(){

    echo "第一个参数为 $1 !"

    echo "第二个参数为 $2 !"

    echo "第十个参数为 $10 !"

    echo "第十个参数为 ${10} !"

    echo "第十一个参数为 ${11} !"

    echo "参数总数有 $# 个!"

    echo "作为一个字符串输出所有参数 $* !"}

funWithParam 1 2 3 4 5 6 7 8 9 34 73

 

输出结果:

第一个参数为 1 !

第二个参数为 2 !

第十个参数为 10 !

第十个参数为 34 !

第十一个参数为 73 !

参数总数有 11 个!

作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !

注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。

 

 

 

 

 

 

特殊符号解释

符号$后的括号

${a} 变量a的值, 在不引起歧义的情况下可以省略大括号。

$(cmd) 命令替换, 结果为shell命令cmd的输出, 和`cmd`效果相同, 不过某些Shell版本不支持$()形式的命令替换, 如tcsh.

$((exp)) 和`expr exp`效果相同, 计算数学表达式exp的数值, 其中exp只要符合C语言的运算规则即可, 甚至三目运算符和逻辑表达式都可以计算.

 

多条命令执行

(cmd1;cmd2;cmd3) 新开一个子shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后可以没有分号.

{ cmd1;cmd2;cmd3;} 在当前shell顺序执行命令cmd1,cmd2,cmd3, 各命令之间用分号隔开, 最后一个命令后必须有分号, 第一条命令和左括号之间必须用空格隔开.

{}和()而言, 括号中的重定向符只影响该条命令, 而括号外的重定向符影响到括号中的所有命令.

 

双括号的特殊用法

(()) 增强括号的用法, 常用于算术运算比较. 双括号中的变量可以不使用$符号前缀, 只要括号中的表达式符合C语言运算规则, 支持多个表达式用逗号分开.

比如可以直接使用for((i=0;i<5;i++)), 如果不使用双括号, 则为for i in `seq 0 4`或者for i in {0..4}.

再如可以直接使用if (($i<5)), 如果不使用双括号, 则为if [ $i -lt 5 ].

[[]] 增强方括号用法, 常用于字符串的比较. 主要用于条件测试, 双括号中的表达式可以使用&&, ||, <, >等C语言语法.

比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ].

 

| 运算符

管道符号,是unix一个很强大的功能,符号为一条竖线:"|"。

用法:

command 1 | command 2

他的功能是把第一个命令command 1执行的结果作为command2的输入传给command 2,例如:

 

$ls -s|sort -nr (请注意不要复制$符号进去哦)

-s 是file size,-n是numeric-sort,-r是reverse,反转

该命令列出当前目录中的文档(含size),并把输出送给sort命令作为输入,sort命令按数字递减的顺序把ls的输出排序。

 

 

&& 运算符:

格式

command1  && command2

&&左边的命令(命令1)返回真(即返回0,成功被执行)后,&&右边的命令(命令2)才能够被执行;换句话说,“如果这个命令执行成功&&那么执行这个命令”。

语法格式如下:

command1 && command2 && command3 ...

命令之间使用 && 连接,实现逻辑与的功能。

只有在 && 左边的命令返回真(命令返回值 $? == 0),&& 右边的命令才会被执行。

只要有一个命令返回假(命令返回值 $? == 1),后面的命令就不会被执行。

例如 make && make install 表示编译成功后安装

posted @ 2019-03-08 16:54  月清水影  阅读(399)  评论(0编辑  收藏  举报