Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。
当一个用户登陆linux 系统后,系统就会为该用户创建一个shell程序。
Shell的版本:
位置变量属于只读变量
作用:向shell脚本传递参数,参数个数可以任意多,但只有前9个被访问到,shift命令可以更改这个限制。
每个访问参数前加$,
第一个参数为0,表示预留保存实际脚本名字,无论脚本是否有参数,此值均可用,如:给脚本test传递信息:
Would you like to do it
$0
$1
$2
$3
$4
$5
$6
$7
$8
$9
脚本名字
would
you
like
to
do
it
例:$ vi test
#!/bin/sh
echo "The full name is : $0 "
echo "The script name is : `basename $0`"
echo "The first parameter is :$1"
echo "The second parameter is :$2"
echo "The third parameter is :$3"
echo "The fourth parameter is :$4"
echo "The fifth parameter is :$5"
echo "The sixth parameter is :$6"
echo "The seventh parameter is :$7"
echo "The eighth parameter is :$8"
echo "The ninth parameter is :$9"
保存文件,执行 $ ./test would you like to do it
The full name is : ./test
The script name is : test
The first parameter is :would
The second parameter is :you
The third parameter is :like
The fourth parameter is :to
The fifth parameter is :do
The sixth parameter is :it
The seventh parameter is :
The eighth parameter is :
The ninth parameter is :
note:上例中$0返回的信息中包含路径名,如果只想得到脚本名称,可以借助basename,将脚本中第一句修改为: echo "The script name is : \`basename \$0\` "
保存文件,执行 ./test would you like to do it
例:修改test脚本,追加特定变量信息: ```shell #!/bin/sh echo "The full name is : $0 " echo "The script name is : `basename $0`" echo "The first parameter is :$1" echo "The second parameter is :$2" echo "The third parameter is :$3" echo "The fourth parameter is :$4" echo "The fifth parameter is :$5" echo "The sixth parameter is :$6" echo "The seventh parameter is :$7" echo "The eighth parameter is :$8" echo "The ninth parameter is :$9"
echo "The number of arguments passed :$#" echo "Show all arguments :$*" echo "Show my process id :$$" echo "Show me the arguments in quotes :$@" echo "Did my script go with any errors :$?" ```
##3.3 if 条件判断 格式: ```shell if 条件1 then 命令1 elif 条件2 then 命令2 else 命令3 fi ``` >注意:使用if语句时,必须将then部分放在新行,否则会产生错误,如果要不分行,必须使用命令分割符,即: ```shell if 条件1; then 命令1 fi ```
例:$ vi myfile ```shell #!/bin/sh DIRECTORY=$1 if [ "`ls -A $DIRECTORY`" = "" ] ; then echo "$DIRECTORY is indeed empty" else echo "$DIRECTORY is not empty" fi ```
##3.4 for 循环 格式: ```shell for 变量名 in 列表 do 命令1 命令2 done ``` >说明:命令 可为任何有效的shell命令和语句 变量名可以为任何单词 in列表是可选的,如果没有列表,for循环会使用命令行的位置参数 in列表可以包含替换,字符串,文件名
例: ```shell #!/bin/sh for loop1 in 1 2 4 5 6 #数字列表 do echo $loop1 done for loop2 in he is a tall man #字符串列表 do echo $loop2 done for loop3 in `ls` #替换列表 do echo $loop3 done ``` 对for 循环使用参数,当循环中省去in列表选项时,它将接受命令行特定变量做为参数,即 ```shell for params in "$@" 或者 for params in "$*" ```
例1: ```shell #!/bin/sh for params in "$@" do echo "You supplied $params as a command line option" done echo $params ``` 例2 ```shell #!/bin/sh counter=0 for files in `ls` do counter=`expr $counter + 1` done echo "There are $counter files in `pwd`" ``` ##3.5 while和until循环 while循环 格式: ```shell while 命令 do 命令1 命令2 …… done ``` >note:do和done之间命令,只有前一个返回状态为0,后面命令才会被执行;否则则循环中止
until循环 格式: ```shell until 条件 do 命令1 命令2 …… done ``` >note:until执行一系列命令,只至条件为真时停止,循环至少执行一次。
例1: ```shell #!/bin/sh echo "Type <Ctrl-D> to terminate" echo -n "enter your favorate film :" while read FILM do echo "Yeah,great film the $FILM" done ``` 使用ctrl-D中断脚本的执行,整个循环中止 例2: ```shell #!/bin/sh IS_ROOT=`who | grep root` until [ "$IS_ROOT" ] do sleep 5 IS_ROOT=`who | grep root` done echo "Watch it. Roots in " | mail chenshifeng ``` 思考:为什么用sleep 5?
##3.6 case 条件选择 格式: ```shell case 值 in 模式1) 命令1 …… ;; 模式2) 命令2 …… ;; esac ``` >case 取值后面必须为in,每个模式必须以右括号结束,取值可以为变量或者常数,找到匹配模式后,执行相关命令直到;;
模式部分可以包含元字符,与命令行中文件扩展名中使用的匹配类型相符,如 * 、? 、 [..] 例: ```shell #!/bin/sh if [ $# != 1 ]; then echo "Usage:`basename $0` [start|stop|help]" exit 1 fi OPT=$1 case $OPT in start) echo "starting..`basename $0`" # code here to start a process ;; stop) echo "stopping..`basename $0`" # code here to stop a process ;; help) # code here to display a help page ;; *) echo "Usage:`basename $0` [start|stop|help]" ;; esac ```
##3.7 break 和continue 有时需要某些准则退出循环或者跳过循环步,就需要break和continue来实现 break 允许跳出循环或者case语句,在嵌套循环里,可以制定跳出的循环个数,例在两层的嵌套循环内,break 2可以跳出整个循环 continue 类似于break,区别是continue只会跳过当前的循环步,而不会跳出整个循环 例子1: ```shell #!/bin/sh while : do echo -n "Enter any number [1..5] :" read ANS case $ANS in 1|2|3|4|5) echo "great you entered a number between 1 and 5" ;; *) echo "wrong number..bye" break ;; esac done ```
例子2 : names2.txt 内容包含雇员名字,部门,及其id,如下所示: ------------------------------内容如下-------------------------------- ---LISTING OF PERSONNEL FILE---- --- TAKEN AS AT 06/1999---------------- Louise Conrad:Accounts:ACC8987 Peter James:Payroll:PR489 Fred Terms:Customer:CUS012 James Lenod:Accounts:ACC887 Frank Pavely:Payroll:PR489 ------------------------------------------------------------------------------- 要求:读取names2.txt文件,将在职员工的名字,部门,部门id读取打印出来 说明:Peter James已经离职
```shell #!/bin/sh # save the setting of IFS SAVEDIFS=$IFS # assign new separator to IFS IFS=: INPUT_FILE=names2.txt NAME_HOLD="Peter James" LINE_NO=0 if [ -s $INPUT_FILE ]; then while read NAME DEPT ID do LINE_NO=`expr $LINE_NO + 1` if [ "$LINE_NO" -le "2" ]; then continue fi if [ "$NAME" = "$NAME_HOLD" ]; then continue else echo "Now processing …$NAME $DEPT $ID" fi done < $INPUT_FILE # restore the settings of IFS IFS=$SAVEDIFS else echo "`basename $0 ` : Sorry file not found or there is no data in the file >&2" exit 1 fi ``` #第四部分 shell 函数 shell 允许将一组命令集或语句形成一个可用块,这些块称为shell函数,其组成部分: 函数标题,函数体 标题是函数名,应该唯一;函数体是命令集合 函数格式: ```shell 函数名() { 命令1 … } 或者 function 函数名() { …. } ``` 函数可以只放在同一个文件中做为一段代码,也可以放在只包含函数的单独文件中 ##4.1 在脚本中定义并使用函数 >注:函数必须在使用前定义,一般放于脚本开始部分,直至shell解释器首次发现它时,才可以使用
例脚本func1: ```shell #!/bin/sh hello() { echo "Hello,today’s date is `date`" } echo "now, going to the function hello" hello echo "back from the function" ``` ##4.2 向函数传递参数 向函数传递参数就象在一般脚本中使用特殊变量`$1,$2..$9`一样,函数取得所传参数后,将原始参数传回`shell`,可以在函数内定义本地变量保存所传的参数,一般这样的参数名称以`_`开头 例:脚本对输入的名字进行检查,只能包含字母 $ vi func2 ```shell #!/bin/sh echo -n "what is your first name :" read F_NAME char_name() { _LETTERS_ONLY=$1 _LETTERS_ONLY=`echo $1|awk '{if($0~/[^a-z A-Z]/) print "1"}'` if [ "$_LETTERS_ONLY" != "" ] then return 1 else return 0 fi } if char_name $F_NAME; then echo "ok" else echo "ERRORS" fi ``` ##4.3 函数返回值 函数执行完毕或者基于某个测试语句返回时,可作两种处理: 1) 让函数正常执行到末尾,然后返回脚本中调用函数的控制部分 2) 使用return 返回脚本中函数调用的下一条语句,可以带返回值, - 0为无错误 - 1为有错误 格式: ```shell return 从函数中返回,用最后状态命令决定返回值 return 0 无错误返回 return 1 有错误返回 ```
##4.4 函数返回值测试: 可以直接在脚本调用函数语句的后面使用最后状态命令来测试函数 调用的返回值 例: ```shell hello #这里是hello函数被调用 if [ $? = 0 ] then echo "it is ok" else echo "something is wrong with hello function" fi ``` 更好的办法是使用if语句测试返回0还是返回1,可以在if语句里面将函数调用用括号括起来,增加可读性,如 if hello ; then
##5.2 使用set命令进行调试 ```shell set -n 读命令但不执行 set -v 显示读取的所有行 set -x 显示所有命令及其参数 set +x set选项关闭 ``` 例:vi error_file ```shell #!/bin/sh set –x LIST="Peter Susan John Barry Lucy Norman Bill Leslie" echo -n "Enter your name :" read NAME for LOOP in $LIST do if [ "$LOOP" = "$NAME" ];then echo "you’re on the list, you’re in" break fi done set +x ```` 运行脚本 ```shell $ ./error_file ``` 执行结果: ```shell error + error + LIST=Peter Susan John Barry Lucy Norman Bill Leslie + echo –n Enter your Name: Harry + [ Peter = Harry ] + [ Susan = Harry ] + [ John = Harry ] + [ Barry = Harry ] + [ Lucy = Harry ] + [ Norman = Harry ] + [ Bill = Harry ] + [ Leslie = Harry ] ```
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探