shell_shell脚本 - CSDN
shell 订阅
在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(命令解析器)。它类似于DOS下的command.com和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。 展开全文
在计算机科学中,Shell俗称壳(用来区别于核),是指“为使用者提供操作界面”的软件(命令解析器)。它类似于DOS下的command.com和后来的cmd.exe。它接收用户命令,然后调用相应的应用程序。
信息
用    途
接收用户命令
中文名
性    质
命令解析器
外文名
shell
shell术语
同时它又是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。在排序算法中,Shell是希尔排序的名称。基本上shell分两大类:一:图形界面shell(Graphical User Interface shell 即 GUI shell)例如:应用最为广泛的 Windows Explorer (微软的windows系列操作系统),还有也包括广为人知的 Linux shell,其中linux shell 包括 X window manager (BlackBox和FluxBox),以及功能更强大的CDE、GNOME、KDE、 XFCE。二:命令行式shell(Command Line Interface shell ,即CLI shell)例如:bash / sh / ksh / csh / zsh(Unix/linux 系统)(MS-DOS系统)cmd.exe/ 命令提示字符(Windows NT 系统)Windows PowerShell(支持 .NET Framework 技术的 Windows NT 系统)传统意义上的shell指的是命令行式的shell,以后如果不特别注明,shell是指命令行式的shell。文字操作系统与外部最主要的接口就叫做shell。shell是操作系统最外面的一层。shell管理你与操作系统之间的交互:等待你输入,向操作系统解释你的输入,并且处理各种各样的操作系统的输出结果。shell提供了你与操作系统之间通讯的方式。这种通讯可以以交互方式(从键盘输入,并且可以立即得到响应),或者以shell script(非交互)方式执行。shell script是放在文件中的一串shell和操作系统命令,它们可以被重复使用。本质上,shell script是命令行命令简单的组合到一个文件里面。Shell基本上是一个命令解释器,类似于DOS下的command。它接收用户命令(如ls等),然后调用相应的应用程序。较为通用的shell有标准的Bourne shell (sh)和C shell (csh)。交互式shell和非交互式shell交互式模式就是shell等待你的输入,并且执行你提交的命令。这种模式被称作交互式是因为shell与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。当你签退后,shell也终止了。shell也可以运行在另外一种模式:非交互式模式。在这种模式下,shell不与你进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾,shell也就终止了。shell的类型在UNIX中主要有:Bourne shell (包括 sh,ksh,and bash)Bourne shell ( sh)Korn shell ( ksh)Bourne Again shell ( bash)POSIX shell ( sh)C shell (包括 csh and tcsh)C shell ( csh)TENEX/TOPS C shell ( tcsh)Bourne Shell  首个重要的标准Unix Shell是1979年底在V7 Unix(AT&T第7版)中引入的,并且以它的创始科技部基础条件平台“国家气象网络计算应用节点建设”(2004DKA50730)资助者Stephen Bourne的名字命名。Bourne shell 是一个交换式的命令解释器和命令编程语言。Bourne shell 可以运行为login shell或者login shell的子shell(subshell)。只有login命令可以调用Bourne shell作为一个login shell。此时,shell先读取/etc/profile文件和$HOME/.profile文件。/etc/profile文件为所有的用户定制环境,$HOME/.profile文件为本用户定制环境。最后,shell会等待读取你的输入。C Shell Bill Joy于20世纪80年代早期,在伯克利的加利福尼亚大学开发了C shell。它主要是为了让用户更容易的使用交互式功能,并把ALGOL风格的语法结构变成了C语言风格。它新增了命令历史、别名、文件名替换、作业控制等功能。Korn Shell 有很长一段时间,只有两类shell供人们选择,Bourne shell用来编程,C shell用来交互。为了改变这种状况,AT&T的bell实验室David Korn开发了Korn shell。ksh结合了所有的C shell的交互式特性,并融入了Bourne shell的语法。因此,Korn shell广受用户的欢迎。它还新增了数学计算,进程协作(coprocess)、行内编辑(inline editing)等功能。Korn Shell 是一个交互式的命令解释器和命令编程语言.它符合POSIX——一个操作系统的国际标准.POSIX不是一个操作系统,而是一个目标在于应用程序的移植性的标准——在源程序一级跨越多种平台。Bourne Again Shell (bash) bash是GNU计划的一部分,用来替代Bourne shell。它用于基于GNU的系统如Linux.大多数的Linux(Red Hat,Slackware,Caldera)都以bash作为缺省的shell,并且运行sh时,其实调用的是bash。POSIX Shell POSIX shell 是Korn shell的一个变种. 当前提供POSIX shell的最大卖主是Hewlett-Packard。在HP-UX 11.0,POSIX shell 就是/bin/sh,而bsh是/usr/old/bin/sh.各主要操作系统下缺省的shell:AIX下是Korn Shell.Solaris缺省的是Bourne shell.FreeBSD缺省的是C shellHP-UX缺省的是POSIX shell.Linux是Bourne Again shell.Windows PowerShell是一种新的交互式的命令行和基于任务脚本编写技术,它使信息技术(IT) 管理员能够全面地自动操作和控制系统管理任务,从而提高了管理员的生产力。Windows PowerShell 包括多个系统管理实用工具、一致的语法和命名惯例、及对普通管理数据更好地导航,如登记、证书存储 或 Windows Management Instrumentation (WMI)。Windows PowerShell 还专门针对 IT 管理,提供直观的脚本编写语言。Shell也是一个VB函数,它的作用是运行程序,语法是Shell(命令字符串[,窗口类型])
收起全文
  • Shell是一个功能相当强大的编程语言,易编写、易调试、灵活性强。Shell可以帮助我们来管理大数据集群,提高开发效率。 本课程详细讲解:Shell解析器、变量、运算符、条件判断、流程控制、函数、cut、sed、awk...
  • 从没上过课的学渣 学了还不会的学弱 想学懂的学霸 10小时全掌握Linux下shell编程 工作、面试全没问题。
  • shell脚本精简教程

    2018-10-22 21:38:06
    详细的介绍shell脚本的使用。
  • Shell脚本编写实战

    2019-06-26 12:12:05
    根据实际的案例讲解怎么编写Shell脚本,在什么场景下编写为讲解导向。 课程内容如下: 1.编写Shell脚本注意事项与编写打印字体颜色函数 2.批量创建用户 3.监控主机存活状态 4.监控CPU、内存、硬盘和网卡流量...
  • 在公司项目的开发过程中,需要编写shell脚本去处理一个业务,在编写过程中发现自身对shell脚本的知识不够完善,顾整理一下,本文章主要内容来自菜鸟教程 , 也添加了一些知识点 shell脚本? 在说什么是shell脚本之前...

    在公司项目的开发过程中,需要编写shell脚本去处理一个业务,在编写过程中发现自身对shell脚本的知识不够完善,顾整理一下,本文章主要内容来自菜鸟教程 , 也添加了一些知识点

    看完这边文章应该就可以独立完成大部分脚本得编写

    shell脚本?

    在说什么是shell脚本之前,先说说什么是shell。

    shell是外壳的意思,就是操作系统的外壳。我们可以通过shell命令来操作和控制操作系统,比如Linux中的Shell命令就包括ls、cd、pwd等等。总结来说,Shell是一个命令解释器,它通过接受用户输入的Shell命令来启动、暂停、停止程序的运行或对计算机进行控制。

    shell 是一个应用程序,它连接了用户和 Linux 内核,让用户能够更加高效、安全、低成本地使用 Linux 内核,这就是 Shell 的本质。

    shell 本身并不是内核的一部分,它只是站在内核的基础上编写的一个应用程序。

    那么什么是shell脚本呢?

    shell脚本就是由Shell命令组成的执行文件,将一些命令整合到一个文件中,进行处理业务逻辑,脚本不用编译即可运行。它通过解释器解释运行,所以速度相对来说比较慢。

    shell脚本中最重要的就是对shell命令的使用与组合,再使用shell脚本支持的一些语言特性,完成想要的功能。

    博主所有文章首发在CSDN 和 公众号:【匠心Java

    【匠心Java】公众号分享工作中涉及到的技术知识,主要分享数据库相关和Java技术干货(JVM+并发+全链路优化);涉及计算机网络、数据结构与算法、linux等编程知识;

    微信扫描下述二维码关注;或微信搜索“匠心Java*”关注,期待与大家的交流

    匠心Java*

    注释

    “# ”开头的就是注释,被编译器忽略

    • 单行注释: #
    • 多行注释: :<<EOF … EOF 或者 :<<! … ! (:<< 标识多行注释开始,并指定一个标识符作为开始结束的标志)

    变量

    变量类型
    运行shell时,会同时存在三种变量:

    1. 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
    2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
    3. shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    变量操作

    • 创建普通变量: name=“test” (=两边不可有空格)
    • 创建只可函数体中使用的局部变量: local name=“test” (使用local修饰的变量在函数体外无法访问,并且local只能在函数体内使用)
    • 使用变量: echo $name 或者 echo ${name} (推荐使用大括号版)
    • 变量重新赋值: name=“new_test” (将原值覆盖)
    • 只读变量: name=“only_read” -> readonly name (使用readonly标识后的变量,不可被修改)
    • 删除变量: unset name; (删除之后不可访问,删除不掉只读变量)

    字符串变量
    1)单引号

    • 单引号变量var='test' ,只能原样输出,变量无效
    • 单引号中不能出现一个单独的单引号,转义也不可以

    2)双引号

    • 双引号变量var="my name is ${name}",变量有效
    • 可出现转义符

    3)拼接字符串

    • 中间无任何+,之类的字符
    • name=“this is”" my name"; name=“this is my name”; name=“this” is “my name” 等效
    • name=‘this is’’ my nam’; name=‘this is my name’; name=‘this’ is ‘my name’ 等效

    4)获取字符串长度

    • 在${}中使用“#”获取长度
    • name=“test”;
    • echo ${#name}; # 输出为4

    5)提取子字符串

    • 1:4 从第2个开始 往后截取4个字符
    • ::4 从第一个字符开始 往后截取4个字符
    • name=“this is my name”;
    • echo ${name:1:4} #输出 is i
    • echo ${name::4} #输出 this

    数组

    bash只支持一维数组,不支持多维数组

    • 定义数组:array_name=(li wang xiang zhang) (小括号做边界、使用空格分离)
    • 单独定义数组的元素: array_para[0]=“w”; array_para[3]=“s” (定义时下标不连续也可以)
    • 赋值数组元素:array_name[0]=“zhao”;
    • 获取数组元素:
      • array_name[0]=“li”
      • array_name[3]=“zhang”
      • echo ${array_name[0]} # 输出"li"
      • echo ${array_name[1]} # 输出" "
      • echo ${array_name[3]} # 输出"zhang"
      • echo ${array_name[@]} # 输出"li zhang" 输出数组所有元素,没有元素的下标省略
    • 取得元素个数:${#array_name[@]} 或者 ${#array_name[*]}
    • 取得单个元素长度:${#array_name[1]}

    参数传递

    • 获取参数值:
      • $0 : 固定,代表执行的文件名
      • $1 : 代表传入的第1个参数
      • $n : 代表传入的第n个参数
    • $#:参数个数
    • $*: 以一个单字符串显示所有向脚本传递的参数。如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数
    • $@:与$*相同,但是使用时加引号,并在引号中返回每个参数。
    • $$:脚本运行的当前进程号
    • $!:后台运行的最后一个进程的ID
    • $?: 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
    • $* 与 $@ 区别
      • 相同点:都是引用所有参数。
      • 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 “1 2 3”(传递了一个参数),而 “@” 等价于 “1” “2” “3”(传递了三个参数)。

    运算符

    算数运算

    • + 、-、*、\ : 乘号前必须加\进行转义才可以进行乘法运算
    • 加法运算
      • val=`expr 2 + 2` (使用linux命令expr进行辅助运算)
      • val=$[2+2] (4个空格不是必要的,不同于条件判断)
      • val=$((2+2))

    数字关系运算符
    关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
    下面假定变量 a 为 10,变量 b 为 20

    • -eq :检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
    • -ne: 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
    • -gt: 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
    • -lt : 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
    • -ge: 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
    • -le : 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。

    字符串运算符
    下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:

    • = :检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
    • != :检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
    • -z :检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
    • -n :检测字符串长度是否为0,不为0返回 true。 [ -n “$a” ] 返回 true。
    • $ :检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。

    布尔运算符
    下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

    • ! :非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
    • -o :或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
    • -a :与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

    逻辑运算符
    以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

    • && :逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
    • || :逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true

    文件运算符

    • -b file :检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
    • -c file :检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
    • -d file :检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
    • -f file :检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
    • -g file :检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
    • -k file :检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
    • -p file :检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
    • -u file :检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
    • -r file :检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
    • -w file :检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
    • -x file :检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
    • -s file :检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
    • -e file :检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。

    执行相关

    命令替换
    命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
    执行命令:

    1. `ls /etc` : 反引号 (所有的unix系统都支持)
    2. $(ls /etc) : $+() (部分unix系统不支持)
      多个嵌套使用时,从内向外执行

    for file in \s /etc\ 或 for file in $(ls /etc) 循环中使用
    `dirname $0` 获取脚本文件所在的目录
    path=$(cd `dirname $0`;pwd) : 获取脚本当前所在目录,并且执行cd命令到达该目录,使用pwd获取路径并赋值到path变量

    算术运算

    1. $[ ] : 加减乘除,不必添加空格
    2. $(( )) :加减乘除等,不必添加空格

    逻辑判断

    1. [ ] : 中括号旁边和运算符两边必须添加空格 (可以使用,不推荐)
    2. [[ ]]:中括号旁边和运算符两边必须添加空格 (字符串验证时,推荐使用)
    3. (()) : 中括号旁边和运算符两边必须添加空格 (数字验证时,推荐使用)
    4. [[]] 和 (()) 分别是[ ]的针对数学比较表达式和字符串表达式的加强版。
    5. 使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
      [[ ]]中增加模式匹配特效;
      (( ))不需要再将表达式里面的大小于符号转义,除了可以使用标准的数学运算符外,还增加了以下符号
      在这里插入图片描述

    输出

    echo
    仅用于字符串的输出,没有使用printf作为输出的移植性好,建议使用printf

    printf

    printf 不会像 echo 自动添加换行符,我们可以手动添加 \n
    无大括号,直接以空格分隔

    • 格式:printf format-string [arguments...] 其中(format-string: 格式控制字符串、arguments: 参数列表)
    • 案例:printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
    • %s %c %d %f 都是格式替代符
      • d:Decimal 十进制整数 对应位置参数必须是十进制整数,否则报错!
      • s:String 字符串 对应位置参数必须是字符串或者字符型 否则报错
      • c:Char 字符 对应位置参数必须是字符串或者字符型 否则报错
      • f:Float 浮点 对应位置参数必须是数字型 否则报错
    • %-10s : 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
    • %-4.2f :指格式化为小数,宽度为4个字符,其中.2指保留2位小数。
    • 转义符:
      • \a :警告字符,通常为ASCII的BEL字符
      • \b :后退
      • \c :抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
      • \f :换页(formfeed)
      • \n :换行
      • \r :回车(Carriage return)
      • \t :水平制表符
      • \v :垂直制表符
      • \ :一个字面上的反斜杠字符
      • \ddd :表示1到3位数八进制值的字符。仅在格式字符串中有效
      • \0ddd :表示1到3位的八进制值字符

    流程控制

    和Java、PHP等语言不一样,sh的流程控制不可为空,即if或者else的大括号中无任何语句
    if else

    • if
    if condition
    then
        command1 
        command2
        ...
        commandN 
    fi
    
    • if else
    if condition
    then
        command1 
        command2
        ...
        commandN
    else
        command
    fi
    
    • if else-if else
    if condition1
    then
        command1
    elif condition2 
    then 
        command2
    else
        commandN
    fi
    

    for

    for var in item1 item2 ... itemN
    do
        command1
        command2
        ...
        commandN
    done
    

    while

    • while condition
    while condition
    do
        command
    done
    
    • while 无限循环
    while :
    do
        command
    done
    

    until
    until 循环执行一系列命令直至条件为 true 时停止。
    until 循环与 while 循环在处理方式上刚好相反。

    until condition
    do
        command
    done
    

    case
    Shell case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
    case需要一个esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break,其中“;;”不是跳出循环,是不在去匹配下面的模式
    case语句格式如下:

    casein
      模式1)
        command1
        command2
        ...
        commandN
        ;;
      模式2)
        command1
        command2
        ...
        commandN
        ;;
    esac
    

    跳出循环

    1. break :跳出总循环
    2. continue:跳出当前循环,继续下一次循环

    定义函数

    可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。

    • 函数定义
    [ function ] funname()
    {
        action;
        [return int;]
    }
    
    • 参数传递
      • 调用函数: fun_name 2 3 4
      • 函数中使用:和shell取用函数相同 $n $# $* $? 或者加上{}
    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
    echo $?  \# 判断执行是否成功
    
    • 函数返回值
      • return字样可存在也可不存在
      • return 只能为 return [0-255],此处的返回可作为函数执行的状态,通过$?获取的便是这个返回值
      • 如果不加return , 则默认最后一条语句的执行状态所为函数执行状态的返回值,如果最后一条语句执行成功,则$?为0,否则不为0
    • 使用函数返回值(Janusgraph图数据库官方启动服务脚本片段)
      • return返回的数字,只是作为函数执行状态的返回值,也就是接下来$?获取的值
      • 对于类似于下面的BIN=\abs_path``语句,获取的是函数体内所有的echo、printf输出组合成的一个字符串
    abs_path() {
        SOURCE="${BASH_SOURCE[0]}"
        while [ -h "$SOURCE" ]; do
            DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
            SOURCE="$(readlink "$SOURCE")"
            [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
        done
        echo "test"  
        echo "$( cd -P "$( dirname "$SOURCE" )" && pwd )"  
        # 此函数的两个echo输出会组合成一个字符串作为下述BIN的值
    }
    
    BIN=`abs_path` # BIN赋值函数返回值,如果没有return,则函数中所有的echo、printf输出组合成一个字符串传入BIN
    path=${BIN}/nodetool # 可直接使用
    

    输入输出重定向

    一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

    • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
    • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
    • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

    默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
    如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

    输入重定向

    1. bash.sh < file : 将脚本的输入重定向到file,由file提供参数

    输出重定向

    1. bash.sh > file : 将脚本的输出数据重定向到file中,覆盖数据
    2. bash.sh >> file : 将脚本的输出数据重定向到file中,追加数据
    3. command >> file 2>&1 : 将 stdout 和 stderr 合并后重定向到 file

    读取外部输入

    命令:read arg (脚本读取外部输入并赋值到变量上)
    在shell脚本执行到上述命令时,停止脚本执行并等待外部输入,将外部输入赋值到arg变量上,继续执行脚本

    文件引用

    引用其他的文件之后,可以使用其变量、函数等等,相当于将引用的文件包含进了当前文件
    两种方式:

    1. . file_path\file_name
    2. source file_path\file_name

    颜色标识

    printf  "\033[32m SUCCESS: yay \033[0m\n";
    printf  "\033[33m WARNING: hmm \033[0m\n";
    printf  "\033[31m ERROR: fubar \033[0m\n";
    

    输出结果:
    在这里插入图片描述

    长句换行

    在shell中为避免一个语句过长,可以使用“\”进行换行
    使用“\”换行,在脚本执行过程中还是当做一行一个语句执行,不同于enter直接换行

    注意:\ 前添加一个空格 。 \ 后无空格直接换行。

     /mysql/bin/mysql \
      -h test_host  -P 000 \
      -u test_user -ptest_password ;
    

    shell操作mysql

    下面案例为登录mysql,并选择操作数据库,之后进行导入数据

     /mysql/mysql/bin/mysql \
      -h test_host  -P 000 \
      -u test_user -ptest_password \
      -e"use test_database; source data_faile; " # -e 代表执行sql语句
    

    -u 用户名
    -p 用户密码
    -h 服务器ip地址
    -D 连接的数据库
    -N 不输出列信息
    -B 使用tab键 代替 分隔符
    -e 执行的SQL语句

    退出脚本

    命令:exit

    在退出脚本时使用不同的错误码,这样可以根据错误码来判断发生了什么错误。

    在绝大多数 shell 脚本中,exit 0 表示执行成功,exit 1 表示发生错误。
    对错误与错误码进行一对一的映射,这样有助于脚本调试。

    命令:set -e 或者 set +e
    set -e表示从当前位置开始,如果出现任何错误都将触发exit。相反,set +e表示不管出现任何错误继续执行脚本。

    如果脚本是有状态的(每个后续步骤都依赖前一个步骤),那么请使用set -e,在脚本出现错误时立即退出脚本。
    如果要求所有命令都要执行完(很少会这样),那么就使用set +e。

    shell脚本调试

    检查是否有语法错误-n
    bash -n script_name.sh
    使用下面的命令来执行并调试 Shell 脚本-x
    bash -x script_name.sh
    调试count_odd_number.sh 程序案例:

    #!/usr/bin.env bash
    
    # 用于计算数组中奇数的和
    # @author liyangyang
    # @time 2019/09/17
    
    sum=0
    for num in 1 2 3 4;do
        re=${num}%2
        if (( ${re} == 1 ));then
            sum=$[${sum}+${num}]
        fi
    done
    echo ${sum}
    
    1. 首先检查有无语法错误:
      bash -n count_odd_number.sh
    2. 没有输出,说明没有错误,开始实际调试:
      bash -x count_odd_number.sh
    3. 调试结果如下:
    + sum=0
    + for num in 1 2 3 4
    + re=1%2
    + ((  1%2 == 1  ))
    + sum=1
    + for num in 1 2 3 4
    + re=2%2
    + ((  2%2 == 1  ))
    + for num in 1 2 3 4
    + re=3%2
    + ((  3%2 == 1  ))
    + sum=4
    + for num in 1 2 3 4
    + re=4%2
    + ((  4%2 == 1  ))
    + echo 4
    4
    

    其中的输出显示了程序执行的每一步,通过观察程序执行的步骤是否满足预期从而达到调试的效果
    带有 + 表示的是 Shell 调试器的输出,不带 + 表示程序的输出。

    案例:

    这是es(ElasticSearch)官方启动服务的脚本,看可不可以理解吧~

    #!/usr/bin/env bash
    
    # CONTROLLING STARTUP:
    #
    # This script relies on a few environment variables to determine startup
    # behavior, those variables are:
    #
    #   ES_PATH_CONF -- Path to config directory
    #   ES_JAVA_OPTS -- External Java Opts on top of the defaults set
    #
    # Optionally, exact memory values can be set using the `ES_JAVA_OPTS`. Note that
    # the Xms and Xmx lines in the JVM options file must be commented out. Example
    # values are "512m", and "10g".
    #
    #   ES_JAVA_OPTS="-Xms8g -Xmx8g" ./bin/elasticsearch
    
    source "`dirname "$0"`"/elasticsearch-env
    
    parse_jvm_options() {
      if [ -f "$1" ]; then
        echo "`grep "^-" "$1" | tr '\n' ' '`"
      fi
    }
    
    ES_JVM_OPTIONS="$ES_PATH_CONF"/jvm.options
    
    ES_JAVA_OPTS="`parse_jvm_options "$ES_JVM_OPTIONS"` $ES_JAVA_OPTS"
    
    # manual parsing to find out, if process should be detached
    if ! echo $* | grep -E '(^-d |-d$| -d |--daemonize$|--daemonize )' > /dev/null; then
      exec \
        "$JAVA" \
        $ES_JAVA_OPTS \
        -Des.path.home="$ES_HOME" \
        -Des.path.conf="$ES_PATH_CONF" \
        -cp "$ES_CLASSPATH" \
        org.elasticsearch.bootstrap.Elasticsearch \
        "$@"
    else
      exec \
        "$JAVA" \
        $ES_JAVA_OPTS \
        -Des.path.home="$ES_HOME" \
        -Des.path.conf="$ES_PATH_CONF" \
        -cp "$ES_CLASSPATH" \
        org.elasticsearch.bootstrap.Elasticsearch \
        "$@" \
        <&- &
      retval=$?
      pid=$!
      [ $retval -eq 0 ] || exit $retval
      if [ ! -z "$ES_STARTUP_SLEEP_TIME" ]; then
        sleep $ES_STARTUP_SLEEP_TIME
      fi
      if ! ps -p $pid > /dev/null ; then
        exit 1
      fi
      exit 0
    fi
    
    exit $?
    

    推荐阅读:
    Git-【技术干货】工作中Git的使用实践
    Git - 使用git不知道内部实现机制怎么行

    如果转载此博文,请附上本文链接,谢谢合作~ :https://blog.csdn.net/CSDN___LYY/article/details/100584638

    如果感觉这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!谢谢大家~
    在这里插入图片描述

    展开全文
  • shell中的${}

    2019-06-04 10:29:45
    1.Shell中变量的原形:${var} 但当你要显示变量值加随意的字符(我这里用_AA)时,就会出错 这时应该用变量的原形:${var},即是加一个大括号来限定变量名称的范围 [root@bogon sh]# aa='ajax' [root@bogon sh]# ...

    1.Shell中变量的原形:${var}

     但当你要显示变量值加随意的字符(我这里用_AA)时,就会出错

    这时应该用变量的原形:${var},即是加一个大括号来限定变量名称的范围

    [root@bogon sh]# aa='ajax'
    [root@bogon sh]# echo $aa
    ajax
    [root@bogon sh]# echo $aa_AA
    
    [root@bogon sh]# echo ${aa}_AA
    ajax_AA

    2.$(cmd)

    echo $(ls) 执行过程 shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出, 再将此输出放到原来命令 echo $(ls)中的 $(ls)位置,即替换了$(ls),再执行echo命令 如下: echo $(ls)被替换成了echo 1.txt 2.txt 这里要注意的是$(cmd)中的命令的错误输出是不会被替换的,替换的只是标准输出

    [root@bogon t]# ls
    1.txt  2.txt
    [root@bogon t]# echo $(ls)
    1.txt 2.txt
    
    [root@bogon t]# var=$(cat 3.txt)
    cat: 3.txt: 没有那个文件或目录
    [root@bogon t]# echo $var
    
    $var显然是空的

    3. 一串的命令执行()和{}

    ()和{}都是对一串的命令进行执行,但有所区别:
    相同点
    ()和{}都是把一串的命令放在括号里面,并且命令之间用;号隔开
    不同点
    ()只是对一串命令重新开一个子shell进行执行,{}对一串命令在当前shell执行

    [root@bogon t]# var=test
    [root@bogon t]# echo $var
    test
    [root@bogon t]# (var=notest;echo $var)
    notest
    [root@bogon t]# echo $var
    test
    [root@bogon t]# { var=notest;echo $var;}
    notest
    [root@bogon t]# echo $var
    notest
    [root@bogon t]#


    ()最后一个命令可以不用分号,{}最后一个命令要用分号
    ()里的第一个命令和左边括号不必有空格,{}的第一个命令和左括号之间必须要有一个空格
    ()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令

    [root@bogon t]# { var1=test1;var2=test2;echo $var1>a;echo $var2;}
    test2
    [root@bogon t]# cat a
    test1
    [root@bogon t]# { var1=test1;var2=test2;echo $var1;echo $var2;}>a
    [root@bogon t]# cat a
    test1
    test2

    4.几种特殊的替换结构:

    ${var:-string},${var:+string},${var:=string},${var:?string}

    (1) ${var:-string} 和 ${var:=string}

    若变量var为空或者未定义,则用在命令行中用string来替换${var:-string}
    否则变量var不为空时,则用变量var的值来替换${var:-string}

    root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:-bcc}
    bcc
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo ${a:-bcc}
    ajax
    [root@bogon ~]# unset a
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:=bbc}
    bbc
    [root@bogon ~]# echo $a
    bbc

    比较 后者发现$var为空时,把string赋值给了var
    后者是一种赋值默认值的常见做法

    (2) ${var:+string}

    规则和上面的完全相反
    即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量var的值,即空值

    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo $a
    ajax
    [root@bogon ~]# echo ${a:+bbc}
    bbc
    [root@bogon ~]# echo $a
    ajax
    [root@bogon ~]# unset a
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:+bbc}
    
    [root@bogon ~]# 

    (3) ${var:?string}

    替换规则:若变量var不为空,则用变量var的值来替换${var:?string}
    若变量var为空,则把string输出到标准错误中,并从脚本中退出。
    可利用此特性来检查是否设置了变量的值

    [root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:?bbc}
    -bash: a: bbc
    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo ${a:?bbc}
    ajax
    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo ${a:-`date`}
    ajax
    [root@bogon ~]# unset a
    [root@bogon ~]# echo ${a:-`date`}
    2017年 02月 21日 星期二 10:13:46 CST
    [root@bogon ~]# echo ${a:-$(date)}
    2017年 02月 21日 星期二 10:13:59 CST
    [root@bogon ~]# b=bbc
    [root@bogon ~]# echo ${a:-$b}
    bbc

    5.$((exp)) POSIX标准的扩展计算
    这种计算是符合C语言的运算符,也就是说只要符合C的运算符都可用在$((exp)),包括三目运算符
    注意:这种扩展计算是整数型的计算,不支持浮点型和字符串等
    若是逻辑判断,表达式exp为真则为1,假则为0

    [root@bogon ~]# echo $(3+2)
    -bash: 3+2: 未找到命令
    
    [root@bogon ~]# echo $((3+2))
    5
    [root@bogon ~]# echo $((3.5+2))
    -bash: 3.5+2: 语法错误: 无效的算术运算符 (错误符号是 ".5+2")
    [root@bogon ~]# echo $((3>2))
    1
    [root@bogon ~]# echo $((3>2?'a':'b'))
    -bash: 3>2?'a':'b': 语法错误: 期待操作数 (错误符号是 "'a':'b'")
    [root@bogon ~]# echo $((3>2?a:b))
    0
    [root@bogon ~]# echo $((a=3+2))
    5
    [root@bogon ~]# echo $((a++))
    5
    [root@bogon ~]# echo $a
    6

    6.四种模式匹配替换结构:

    ${var%pattern},${var%%pattern} 从右边开始匹配
    ${var#pattern},${var##pattern} 从左边开始匹配
    ${var%pattern} ,${var#pattern} 表示最短匹配,匹配到就停止,非贪婪
    ${var%%pattern},${var##pattern} 是最长匹配

    结构中的pattern支持通配符
    * 表示零个或多个任意字符
    ?表示零个或一个任意字符
    [...]表示匹配中括号里面的字符
    [!...]表示不匹配中括号里面的字符

     

    ${#var} 可计算出变量值的长度:

    ${#file} 可得到 27 ,因为/dir1/dir2/dir3/my.file.txt 是27个字节

     

    展开全文
  • Shell

    2020-05-17 20:31:22
    shell 1、shell概念 Shell是一种C语言编写的程序,使用户使用Linux的桥梁,Shell即使一种命令语言又是一种编程语言。 shell是指一种应用程序,这个应用程序提供了一种界面,用户通过这个界面访问操作系统内核的服务...

    shell

    1、shell概念

    Shell是一种C语言编写的程序,使用户使用Linux的桥梁,Shell即使一种命令语言又是一种编程语言。
    shell是指一种应用程序,这个应用程序提供了一种界面,用户通过这个界面访问操作系统内核的服务。

    Linux中默认的shell是/bin/bash (重点)。bash shell是大多数Linux系统默认使用的shell,是一个免费版本。

    2、shell入门

    编写规范:
    (1)代码规范:
    #!/bin/bash 就是指定解释器的路径。
    shell相关指令
    (2)文件命名规范:
    文件名.sh

    使用流程:
    (1)创建一个.sh文件 touch/vim
    (2)编写shell代码
    (3)执行shell脚本 因此脚本必须具有执行权限

    案例1: 创建test.sh,实现第一个shell脚本程序,输出hello.world
    输出命令:echo
    比如要输出123,则写成 echo 123,则会在屏幕上打印出123
    注意输出内容:如果包含字母和符号(数字等),则需要用引号包括起来;但如果是纯数字,可以用引号也可以不用
    还要注意:shell语言中一句结束可以加分号也可以不加分号

    #!/bin/bash
    echo "hello world"
    

    注意:刚建好文件.sh后,可能没有执行权限,需要chmod u+x test.sh添加执行权限,然后才能继续执行。
    执行时一定要写成./test.sh,而不是test.sh,运行其他二进制程序也这样,直接写成test.sh,Linux系统会去PATH(环境变量)里寻找有没有叫test.sh的。所以写成test.sh是会找不到命令的,要用./test.sh告诉系统说,就在当前目录找。

    案例2: 使用root用户账号创建并执行test2.sh,实现创建一个shelltest用户,并在家目录创建文件try.html

    #!/bin/bash
    useradd shelltest
    touch /home/shelltest/try.html
    

    3、shell进阶(重点)

    1、变量

    在使用变量的时候一定需要在变量名前面添加一个$符号,该要求在其他语言中也存在的。
    例如:
    定义形如:
    class_name=“yunwei”
    echo $class_name;

    (1)关于单双引号的问题:
    双引号能够识别变量;而且还可以实现转义:

    #!/bin/bash
    str="hello";
    echo "$str"
    
    输出:hello ,其实不加引号也是可以的
    

    单引号只能原样输出,且不能实现转义:

    #!/bin/bash
    str="hello";
    echo ‘$str’
    
    输出:$str 
    

    案例1: 定义一个变量,输出当前时间,要求格式是“年-月-日 时:分:秒”:

    #!/bin/bash
    str=`date "+%F %t"`
    echo $str
    

    注:此处需要加上反引号(esc键下方的那个键),当在脚本中需要执行一些指令并且将执行的结果赋给变量的时候需要使用“反引号”。

    (2)只读变量
    一旦定义就不能别修改了
    语法:readonly 变量名

    案例:定义一个变量a,并且其值为10,随后设置其为只读变量

    #!/bin/bash
    a=10
    readonly a;
    

    (3)接受用户输入(重点)
    语法:read -p 提示信息 变量名

    案例:编写一个脚本,要求执行之后提示用户输入一个文件的路径,自动为用户穿件该文件。

    #!/bin/bash
    read -p "请输入文件路径" filepath
    touch $filepath
    echo "文件创建完成"
    

    (4)删除变量
    语法:unset 变量名

    2、条件判断语句

    语法1:

    if contion
    then
    	command1
    	command2
    	...
    fi
    

    语法2:

    if contion1
    then
    	commamd1
    elif contion2
    then
    	command2
    else
    	command3
    fi
    
    3、运算符

    shell中,常见的运算符有算术运算符、关系运算符、逻辑运算符、字符串运算符、文件测试运算符等。

    (1)算术运算符:
    加减乘除、取余(%),赋值(=)、相等(==)相等返回true、不相等(!=)不相等返回true

    注意: 条件表达式要放在方括号之间,并且要有空格,例如:[$a==$b]是错误的,必须写成[ $a==$b ]。

    原生的bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr,expr最常用。
    expr是一款表达式计算工具,使用它能完成表达式的求值操作。例如:

    #!/bin/bash
    val=`expr 2 + 2`
    echo "两数之和为:$val"
    
    两点注意:
    表达式和运算符之间要有空格,例如2+2是不对的,必须写成2 + 2,这与我们熟悉的大多数编程语言不一样;
    完整的表达式要被``包含,注意这个字符不是常用的单引号,在esc建下边
    
    #!/bin/bash
    a=10
    b=10
    echo "a+b:" expr $a + $b
    

    案例:

    #!/bin/bash
    a=10
    b=10
    if [ $a == $b ]
    then
    	echo "a==b"
    else
    	echo "a!=b"
    fi
    注意:if和[]之间也有空格 
    

    (2)关系运算符
    关系运算符只支持数字,不支持字符串,除非字符串的值是数字
    常见的关系运算符:
    -eq:检测两个数是否相等,相等返回true (equal)
    -ne:检测两个数是否不相等,不相等返回true (not equal)
    -gt:检测左边数是否大于右边的数 (great than)
    -lt:检测左边的数是否小于右边的数 (less than)
    -ge:检测左边的数是否大于等于右边的数
    -le:检测左边的数是否小于等于右边的数

    #!/bin/bash
    if [ $a -eq $b ]
    ...
    

    (3)逻辑运算符
    常见的逻辑运算符:
    l:非运算,表达式为true,则返回false [ ! false ]
    -o:或运算,有一个为真则为真 [ $a -lt 20 -o $b -gt 100 ]
    -a:与运算

    (4)字符串运算符
    常见的字符串运算符,假定变量a为“abc”,变量b为“egf”:
    =:检测两个字符串是否相等,相等返回true
    !=:检测两个字符串是否不相等,不相等返回true
    -z:检测字符串长度是否为0,为0返回true [ -z $a ]
    -n:检测字符串长度是否不为0,不为0返回true
    str:检测字符串是否为空,不为空返回true , [ $a ]返回true

    (5)文件测试运算符(重点)
    文件测试运算符用于检测Unix/Linux文件的各种属性。
    属性检测描述如下:
    -d file:检测文件是否是目录,如果是,则返回true [ -d $file ]
    -f file:检测文件是否是普通文件(既不是目录也不是设备文件),
    如 [ -f $file ]返回true
    -r file:检测文件是否可读,如果是,返回true
    -w file:检测文件是否可写
    -x file:检测文件是否可执行
    -s file:检测文件是否为空(文件大小是否大于0),不为空返回true
    -e file:检测文件(包括目录)是否存在,如果是,则返回true

    (6)shell脚本附带选项(重点)
    在linux shell中如何处理tail -10 access.log这样的命令行选项呢??
    步骤:
    调用tail指令
    系统把后续选项传递给tail
    tail先去打开指定的文件
    取出最后10行

    问题:自己写的shell是否也可以像内置命令一样传递一些选项呢??
    答:可以的,传递方式与上述的描述是一样的,关键是怎么接受。例如:
    传递:

    #./test.sh a b c
    

    接受:
    在脚本中可以使用"$1"来表示a,"$2"来表示b,以此类推,即:接受可以使用"$"加上选项对应的序号即可。$0表示本文件。
    在test.sh中:

    #!/bin/bash
    echo $1 $2 $3
    输出结果是:a b c
    如果加上$0,最后会输出:
    ./test.sh a b c
    

    上述例子就是:传递a b c ,输出其值,其中$1、$2是变量。

    案例:
    创建自定义指令"user" ,可以直接执行,要求该指令具备以下语法和功能:
    a.#user -add 用户名 【添加用户】
    b.#user -del 用户名 【删除用户及其家目录】

    test.sh文件中:

    #!/bin/bash
    if [ $1 = '-add' ]
    then 
    	useradd $2
    else
    	userdel -r $2
    fi
    
    注意:是[ $1 = '-add' ]而不是[ $1 = 'add' ]add之前缺少一个-;
    还有:比较字符串是否相等时使用的是=,一个等于号
    

    传递:

    ./test.sh -add user01
    

    还需要使用到别名:因为题目中要求是指令
    别名的用法:

    vim ~/.bashrc 
    在该文件中按示例添加一行:
    alias user="/root/test.sh"
    写完之后保存即可
    

    之后直接在命令行输入以下就可以了:

    #user -add user01
    

    选型的作用:可以帮助我们将一些复杂了命令直接写成一个,比如我们还可以判断用户是否存在,不存在再去创建

    展开全文
  • 查看脚本语法是否有错误:bash -n modify_suffix.sh跟踪执行sh -x modify_suffix.sh aaa1.${var} 2.$(cmd) 3.()和{} 4.${var:-string},${var:+string},${var:=string},${var:?string} 5.$((exp)) ...

    查看脚本语法是否有错误:
    bash -n modify_suffix.sh
    跟踪执行
    sh -x modify_suffix.sh aaa

    1.${var} 
    2.$(cmd) 
    3.()和{} 
    4.${var:-string},${var:+string},${var:=string},${var:?string} 
    5.$((exp)) 
    6.$(var%pattern),$(var%%pattern),$(var#pattern),$(var##pattern)

    1.Shell中变量的原形:${var}

     但当你要显示变量值加随意的字符(我这里用_AA)时,就会出错

    这时应该用变量的原形:${var},即是加一个大括号来限定变量名称的范围

    复制代码
    [root@bogon sh]# aa='ajax'
    [root@bogon sh]# echo $aa
    ajax
    [root@bogon sh]# echo $aa_AA
    
    [root@bogon sh]# echo ${aa}_AA
    ajax_AA
    复制代码

    批量修改一个目录里文件名

    复制代码
    [root@bogon ~]# cat modify_suffix.sh
    #!/bin/bash
    dst_path=$1
    for file in `ls $dst_path`
    do
            if [ -d $1/$file ]
                     then echo `$0 $1/$file`
            elif [ -f $1/$file ]
                    then    mv $1/$file $1/${file}._mod
            else
                echo $1/${file} is unknow file type
            fi
    
    done;
    ./modify_suffix.sh  ./f
    将 ./f 下的所有文件文件名添加了.mod
    复制代码
    按 Ctrl+C 复制代码
    [root@bogon ~]# file="modify_suffix.sh.tar.gz"
    [root@bogon ~]# echo "${file%%.*}"
    modify_suffix
    [root@bogon ~]# echo "${file%.*}"
    modify_suffix.sh.tar
    [root@bogon ~]# echo "${file#*.}"
    sh.tar.gz
    [root@bogon ~]# echo "${file##*.}"
    gz
    按 Ctrl+C 复制代码

    2.$(cmd)

    [root@bogon t]# ls
    1.txt  2.txt
    [root@bogon t]# echo $(ls)
    1.txt 2.txt
    复制代码
    echo $(ls) 执行过程
    shell扫描一遍命令行,发现了$(cmd)结构,便将$(cmd)中的cmd执行一次,得到其标准输出,
    再将此输出放到原来命令 echo $(ls)中的 $(ls)位置,即替换了$(ls),再执行echo命令
    如下:
    echo $(ls)被替换成了echo 1.txt 2.txt
    这里要注意的是$(cmd)中的命令的错误输出是不会被替换的,替换的只是标准输出
    复制代码
    [root@bogon t]# var=$(cat 3.txt)
    cat: 3.txt: 没有那个文件或目录
    [root@bogon t]# echo $var
    
    $var显然是空的

    3、一串的命令执行()和{}
    ()和{}都是对一串的命令进行执行,但有所区别:
    相同点:
    ()和{}都是把一串的命令放在括号里面,并且命令之间用;号隔开
    不同点
    ()只是对一串命令重新开一个子shell进行执行,{}对一串命令在当前shell执行
    ()最后一个命令可以不用分号,{}最后一个命令要用分号
    ()里的第一个命令和左边括号不必有空格,{}的第一个命令和左括号之间必须要有一个空格
    ()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令

    复制代码
    [root@bogon t]# var=test
    [root@bogon t]# echo $var
    test
    [root@bogon t]# (var=notest;echo $var)
    notest
    [root@bogon t]# echo $var
    test
    [root@bogon t]# { var=notest;echo $var;}
    notest
    [root@bogon t]# echo $var
    notest
    [root@bogon t]#
    复制代码

    在{}中 第一个命令和{之间必须有空格,结束必须有;
    {}中的修改了$var的值 说明在当前shell执行

    复制代码
    [root@bogon t]# { var1=test1;var2=test2;echo $var1>a;echo $var2;}
    test2
    [root@bogon t]# cat a
    test1
    [root@bogon t]# { var1=test1;var2=test2;echo $var1;echo $var2;}>a
    [root@bogon t]# cat a
    test1
    test2
    脚本实例
    (
        echo "1"
        echo "2"
    ) | awk '{print NR,$0}'
    复制代码

    4.几种特殊的替换结构:

    ${var:-string},${var:+string},${var:=string},${var:?string}


    (1)

    ${var:-string} 和 ${var:=string}

    若变量var为空或者未定义,则用在命令行中用string来替换${var:-string}
    否则变量var不为空时,则用变量var的值来替换${var:-string}

    复制代码
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:-bcc}
    bcc
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo ${a:-bcc}
    ajax
    [root@bogon ~]# unset a
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:=bbc}
    bbc
    [root@bogon ~]# echo $a
    bbc
    复制代码

    发现

    ${var:-string}和${var:=string}

    比较 后者发现$var为空时,把string赋值给了var
    后者是一种赋值默认值的常见做法

    (2) ${var:+string}
    规则和上面的完全相反
    即只有当var不是空的时候才替换成string,若var为空时则不替换或者说是替换成变量var的值,即空值

    复制代码
    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo $a
    ajax
    [root@bogon ~]# echo ${a:+bbc}
    bbc
    [root@bogon ~]# echo $a
    ajax
    [root@bogon ~]# unset a
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:+bbc}
    
    [root@bogon ~]# 
    复制代码

    (3). ${var:?string}
    替换规则:若变量var不为空,则用变量var的值来替换${var:?string}
    若变量var为空,则把string输出到标准错误中,并从脚本中退出。
    可利用此特性来检查是否设置了变量的值

    复制代码
    [root@bogon ~]# echo $a
    
    [root@bogon ~]# echo ${a:?bbc}
    -bash: a: bbc
    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo ${a:?bbc}
    ajax
    [root@bogon ~]# a=ajax
    [root@bogon ~]# echo ${a:-`date`}
    ajax
    [root@bogon ~]# unset a
    [root@bogon ~]# echo ${a:-`date`}
    2017年 02月 21日 星期二 10:13:46 CST
    [root@bogon ~]# echo ${a:-$(date)}
    2017年 02月 21日 星期二 10:13:59 CST
    [root@bogon ~]# b=bbc
    [root@bogon ~]# echo ${a:-$b}
    bbc
    复制代码

    5.$((exp)) POSIX标准的扩展计算
    这种计算是符合C语言的运算符,也就是说只要符合C的运算符都可用在$((exp)),包括三目运算符
    注意:这种扩展计算是整数型的计算,不支持浮点型和字符串等
    若是逻辑判断,表达式exp为真则为1,假则为0

    复制代码
    [root@bogon ~]# echo $(3+2)
    -bash: 3+2: 未找到命令
    
    [root@bogon ~]# echo $((3+2))
    5
    [root@bogon ~]# echo $((3.5+2))
    -bash: 3.5+2: 语法错误: 无效的算术运算符 (错误符号是 ".5+2")
    [root@bogon ~]# echo $((3>2))
    1
    [root@bogon ~]# echo $((3>2?'a':'b'))
    -bash: 3>2?'a':'b': 语法错误: 期待操作数 (错误符号是 "'a':'b'")
    [root@bogon ~]# echo $((3>2?a:b))
    0
    [root@bogon ~]# echo $((a=3+2))
    5
    [root@bogon ~]# echo $((a++))
    5
    [root@bogon ~]# echo $a
    6
    复制代码

    6.四种模式匹配替换结构:

    复制代码
    ${var%pattern}
    ${var%%pattern}
    ${var#pattern}
    ${var##pattern}
    
    ${var%pattern},${var%%pattern} 从右边开始匹配
    ${var#pattern},${var##pattern} 从左边开始匹配
    ${var%pattern} ,${var#pattern} 表示最短匹配,匹配到就停止,非贪婪
    ${var%%pattern},${var##pattern} 是最长匹配
    复制代码

    只有在pattern中使用了通配符才能有最长最短的匹配,否则没有最 长最短匹配之分
    结构中的pattern支持通配符
    * 表示零个或多个任意字符
    ?表示零个或一个任意字符
    [...]表示匹配中括号里面的字符
    [!...]表示不匹配中括号里面的字符

    复制代码
    [root@bogon ~]# f=a.tar.gz
    [root@bogon ~]# echo ${f##*.}
    gz
    [root@bogon ~]# echo ${f%%.*}
    a
    [root@bogon ~]# var=abcdccbbdaa
    [root@bogon ~]# echo ${var%%d*}
    abc
    [root@bogon ~]# echo ${var%d*}
    abcdccbb
    [root@bogon ~]# echo ${var#*d}
    ccbbdaa
    [root@bogon ~]# echo ${var##*d}
    aa
    #发现输出的内容是var去掉pattern的那部分字符串的值

    假设我们定义了一个变量为:
    file=/dir1/dir2/dir3/my.file.txt

    可以用${ }分别替换得到不同的值:
    ${file#*/}:删掉第一个 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
    ${file##*/}:删掉最后一个 /  及其左边的字符串:my.file.txt
    ${file#*.}:删掉第一个 .  及其左边的字符串:file.txt
    ${file##*.}:删掉最后一个 .  及其左边的字符串:txt
    ${file%/*}
    :删掉最后一个  /  及其右边的字符串:/dir1/dir2/dir3
    ${file%%/*}:删掉第一个 /  及其右边的字符串:(空值)
    ${file%.*}:删掉最后一个  .  及其右边的字符串:/dir1/dir2/dir3/my.file
    ${file%%.*}:删掉第一个  .   及其右边的字符串:/dir1/dir2/dir3/my

    记忆的方法为:
    # 是 去掉左边(键盘上#在 $ 的左边)
    %是去掉右边(键盘上% 在$ 的右边)
    单一符号是最小匹配;两个符号是最大匹配
    ${file:0:5}:提取最左边的 5 个字节:/dir1
    ${file:5:5}
    :提取第 5 个字节右边的连续5个字节:/dir2

    也可以对变量值里的字符串作替换:
    ${file/dir/path}
    :将第一个dir 替换为path/path1/dir2/dir3/my.file.txt
    ${file//dir/path}
    :将全部dir 替换为 path/path1/path2/path3/my.file.txt

    利用 ${ } 还可针对不同的变数状态赋值(沒设定、空值、非空值) 
    ${file-my.file.txt} 
    :假如 $file 沒有设定,則使用 my.file.txt 作传回值。(空值及非空值時不作处理
    ${file:-my.file.txt} 
    :假如 $file 沒有設定或為空值,則使用 my.file.txt 作傳回值。 (非空值時不作处理)
    ${file+my.file.txt} 
    :假如 $file 設為空值或非空值,均使用 my.file.txt 作傳回值。(沒設定時不作处理)
    ${file:+my.file.txt} 
    :若 $file 為非空值,則使用 my.file.txt 作傳回值。 (沒設定及空值時不作处理)
    ${file=my.file.txt} 
    :若 $file 沒設定,則使用 my.file.txt 作傳回值,同時將 $file 賦值為 my.file.txt  (空值及非空值時不作处理)
    ${file:=my.file.txt} 
    :若 $file 沒設定或為空值,則使用 my.file.txt 作傳回值,同時將 $file 賦值為 my.file.txt  (非空值時不作处理)
    ${file?my.file.txt} 
    :若 $file 沒設定,則將 my.file.txt 輸出至 STDERR (空值及非空值時不作处理)

    ${file:?my.file.txt} :若 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR (非空值時不作处理)

    ${#var} 可计算出变量值的长度:

    ${#file} 可得到 27 ,因为/dir1/dir2/dir3/my.file.txt 27个字节

    转载:https://blog.csdn.net/shmilyringpull/article/details/7631106


    展开全文
  • 一.Shell简介 Shell是一个用C语言编写的程序,通过Shell用户可以访问操作系统内核服务,类似于DOS下的command和后来的cmd.exe。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行...

    原文地址: Shell——你只需要了解这么多

    一.Shell简介

    Shell是一个用C语言编写的程序,通过Shell用户可以访问操作系统内核服务,类似于DOS下的command和后来的cmd.exe。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量、参数、函数、流程控制等等。它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。因此,对于用户来说,shell是最重要的实用程序,深入了解和熟练掌握shell的特性极其使用方法,是用好Unix/Linux系统的关键。

    二.两类程序设计语言

    我经常说道shell脚本,其实是因为Shell是一种脚本语言,也就是解释性语言。程序设计语言可以分为两类:编译型语言和解释型语言。

    语言 区别
    编译型语言 需要预先将我们写好的源代码转换成目标代码,这个过程被称作“编译”。运行程序时,直接读取目标代码。由于编译后的目标代码非常接近计算机底层,因此执行效率很高,这是编译型语言的优点
    解释型语言 也叫做脚本语言。执行这类程序时,解释器需要读取我们编写的源代码,并将其转换成目标代码,再由计算机运行。因为每次执行程序都多了编译的过程,因此效率有所下降

    三.Shell脚本解释器

    Linux的Shell脚本解释器种类众多,一个系统可以存在多个shell脚本解释器,可以通过cat /etc/shells 命令查看系统中安装的shell脚本解释器。

    [root@centos6-1 ~]# cat /etc/shells 
    /bin/sh
    /bin/bash
    /sbin/nologin
    /bin/dash
    /bin/tcsh
    /bin/csh
    [root@centos6-1 ~]# 
    

    bash由于易用和免费,在日常工作中被广泛使用。同时,Bash也是大多数Linux系统默认的Shell脚本解释器。

    四.Hello World

    新建helloworld.sh

    [root@centos6-1 ~]# touch helloworld.sh
    

    编辑helloworld.sh文件,添入一下内容

    #!/bin/bash
    echo "helloworld"
    
    • #! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell,这里指定bash
    • echo 是Shell的一个内部指令,用于在屏幕上打印出指定的字符串

    赋予当前用户helloworld.sh的执行权限(刚创建的文件没有执行权限)

    [root@centos6-1 ~]# chmod u+x helloworld.sh
    

    执行hellowo.sh脚本方式一

    [root@centos6-1 ~]# ./helloworld.sh 
    helloworld
    [root@centos6-1 ~]# 
    

    注意,一定要写成./helloworld.sh,而不是helloworld.sh,linux系统会去PATH里寻找有没有叫helloworld.sh的,而helloworld.sh不在PATH里,所以写成helloworld.sh是会找不到命令的,要用./helloworld.sh告诉系统说,就在当前目录找。
    执行hellowo.sh脚本方式二

    [root@centos6-1 ~]# /bin/sh helloworld.sh 
    helloworld
    [root@centos6-1 ~]# 
    

    这种运行方式是,直接运行解释器,其参数就是shell脚本的文件名,当使用这种方式时,脚本中的#!/bin/bash指定的解释器是不生效的,当前使用什么解释器就是什么解释器

    五.变量

    • 语法格式:变量名=变量值

    shell变量定义的严格语法限制:

    1. 变量名和等号之间不能有空格
    2. 变量名首个字符必须为英文字母
    3. 不能包含标点符号但能够使用下划线(_)
    4. 不能使用空格
    5. 不能使用 bash 里的关键字
    

    1.变量类型

    类型 解释
    局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量
    环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程 序需要环境变量来保证其正常运行。可以用过set命令查看当前环境变量
    shell变量 由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell 的正常运行

    2.定义变量

    name="zaomianbao"
    

    3.引用变量

    name="zaomianbao"
    echo ${name}
    echo $name
    

    引用一个定义过的变量,只要在变量名前面加$即可,变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界。

    4.重新定义变量

    已定义的变量,可以被重新定义

    name="zaomianbao"
    echo ${name}
    name="tiechui"
    echo ${name}
    

    5.只读变量

    使用readonly命令可以将变量定义为只读变量,只读变量的值不能被改变

    name="zaomianbao"
    readonly name
    name="tiechui"
    

    6.删除变量

    name="zaomianbao"
    unset name
    echo $name
    

    使用unset命令可以删除变量,变量被删除后不能再次使用,同时unset命令不能删除只读变量。

    六.参数传递

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

    1.修改helloworld.sh为

    #!/bin/bash
    echo $1
    echo $2
    echo $3
    

    2.执行携带参数

    [root@centos6-1 ~]# ./helloworld.sh haha wowow nini
    haha
    wowow
    nini
    [root@centos6-1 ~]#
    

    七.特殊字符

    字符 意义
    $# 传递到脚本的参数个数
    $* 以一个单字符串显示所有向脚本传递的参数
    $$ 脚本运行的当前进程ID号
    $! 后台运行的最后一个进程的ID号
    $@ 与$*相同,但是使用时加引号,并在引号中返回每个参数
    $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误

    $*和$@区别:

    • 相同点:都表示传递给脚本的所有参数。
    • 不同点:不被" “包含时,$和$@都以$1 $2… $n 的形式组成参数列表。
      被" “包含时,”$
      ” 会将所有的参数作为一个整体,以"$1 $2 … $n" 的形式组成一个整串;"$@" 会将各个参数分开,以"$1" “$2” … “$n” 的 形式组成一个参数列表。

    八.Shell字符串

    shell字符串可以用单引号,也可以用双引号,也可以不用引号

    单引号

    name='my name is zaomianbao'
    
    • 单引号字符串中不支持引用变量,任何字符都会原样输出
    • 单引号字串中不能出现单引号(对单引号使用转义符后也不行)

    双引号

    name='my name is zaomianbao'
    name_again="\"${name}\""
    
    • 双引号里可以引有变量
    • 双引号里支持转义字符

    字符串长度

    name='my name is zaomianbao'
    echo ${#name}   //执行输出为21
    

    截取字符串

    name='my name is zaomianbao'
    echo ${name:11:20}   //执行输出zaomianbao
    

    九.shell数组

    • bash支持一维数组(不支持多维数组),并且没有限定数组的大小。在Shell中,用括号来表示数组,数组元素用“空格”符号分割开。定义数组的一般形式为:
        array_name=(value1 … valuen)

    下面的例子将展示shell数组常见的所有操作

    //第一数组
    [root@centos6-1 ~]# usernames=(1 2 33 44 adsd1)
    //默认读取第一个
    [root@centos6-1 ~]# echo ${usernames}
    1
    //读取下标为0的
    [root@centos6-1 ~]# echo ${usernames[0]}
    1
    //读取下标为1的
    [root@centos6-1 ~]# echo ${usernames[1]}
    2
    //读取所有
    [root@centos6-1 ~]# echo ${usernames[*]}
    1 2 33 44 adsd1
    //同样是读取所有
    [root@centos6-1 ~]# echo ${usernames[@]}
    1 2 33 44 adsd1
    //获取数组长度
    [root@centos6-1 ~]# echo ${#usernames[@]}
    5
    //同样可以获取数组长度
    [root@centos6-1 ~]# echo ${#usernames[*]}
    5
    [root@centos6-1 ~]# 
    

    十.shell运算符

    • Shell和其他编程语音一样,支持包括:算术、关系、布尔、字符串等运算符。
    • 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

    1.算术运算符

    运算符 意义
    + 加法
    - 减法
    * 乘法
    / 除法
    % 模,即取余

    下面是详细例子

    #!/bin/bash
    
    a=10
    b=20
    
    val=`expr $a + $b`
    echo "a + b : $val"
    
    val=`expr $a - $b`
    echo "a - b : $val"
    
    val=`expr $a \* $b`
    echo "a * b : $val"
    
    val=`expr $b / $a`
    echo "b / a : $val"
    
    val=`expr $b % $a`
    echo "b % a : $val"
    
    if [ $a == $b ]
    then
       echo "a 等于 b"
    fi
    if [ $a != $b ]
    then
       echo "a 不等于 b"
    fi
    

    执行

    [root@centos6-1 ~]# ./helloworld.sh 
    a + b : 30
    a - b : -10
    a * b : 200
    b / a : 2
    b % a : 0
    a 不等于 b
    [root@centos6-1 ~]# 
    

    注意:

    -  1.乘号(*)前边必须加反斜杠(\)
    -  2.条件表达式要放在方括号之间,并且要有空格
    

    2.关系运算符

    关系运算符只支持数字,不支持字符串,除非字符串的值是数字

    运算符 意义
    -eq EQUAL等于
    -ne NOT EQUAL不等于
    -gt GREATER THAN大于
    -lt LESS THAN小于
    -ge GREATER THAN OR EQUAL 大于等于
    -le LESS THAN OR EQUAL 小于等

    下面是详细例子

    #!/bin/bash
    
    a=10
    b=20
    
    if [ $a -eq $b ]
    then
       echo "$a -eq $b : a 等于 b"
    else
       echo "$a -eq $b: a 不等于 b"
    fi
    if [ $a -ne $b ]
    then
       echo "$a -ne $b: a 不等于 b"
    else
       echo "$a -ne $b : a 等于 b"
    fi
    if [ $a -gt $b ]
    then
       echo "$a -gt $b: a 大于 b"
    else
       echo "$a -gt $b: a 不大于 b"
    fi
    if [ $a -lt $b ]
    then
       echo "$a -lt $b: a 小于 b"
    else
       echo "$a -lt $b: a 不小于 b"
    fi
    if [ $a -ge $b ]
    then
       echo "$a -ge $b: a 大于或等于 b"
    else
       echo "$a -ge $b: a 小于 b"
    fi
    if [ $a -le $b ]
    then
       echo "$a -le $b: a 小于或等于 b"
    else
       echo "$a -le $b: a 大于 b"
    fi
    

    执行

    [root@centos6-1 ~]# ./helloworld.sh  
    10 -eq 20: a 不等于 b
    10 -ne 20: a 不等于 b
    10 -gt 20: a 不大于 b
    10 -lt 20: a 小于 b
    10 -ge 20: a 小于 b
    10 -le 20: a 小于或等于 b
    [root@centos6-1 ~]# 
    

    3.布尔运算符

    运算符 意义
    &&
    ||

    下面是详细例子

    #!/bin/bash
    
    a=10
    b=20
    
    if [[ $a -lt 100 && $b -gt 100 ]]
    then
       echo "返回 true"
    else
       echo "返回 false"
    fi
    
    if [[ $a -lt 100 || $b -gt 100 ]]
    then
       echo "返回 true"
    else
       echo "返回 false"
    fi
    

    执行

    [root@centos6-1 ~]# ./helloworld.sh 
    返回 false
    返回 true
    [root@centos6-1 ~]# 
    

    4.字符串运算符

    操作符 意义
    -z 字符串长度是否为0,为0返回 true
    -n 字符串长度是否为0,不为0返回 true
    str 字符串是否为空,不为空返回 true

    下面是详细例子

    #!/bin/bash
    
    a="abc"
    b="efg"
    
    if [ $a = $b ]
    then
       echo "$a = $b : a 等于 b"
    else
       echo "$a = $b: a 不等于 b"
    fi
    if [ $a != $b ]
    then
       echo "$a != $b : a 不等于 b"
    else
       echo "$a != $b: a 等于 b"
    fi
    if [ -z $a ]
    then
       echo "-z $a : 字符串长度为 0"
    else
       echo "-z $a : 字符串长度不为 0"
    fi
    if [ -n $a ]
    then
       echo "-n $a : 字符串长度不为 0"
    else
       echo "-n $a : 字符串长度为 0"
    fi
    if [ $a ]
    then
       echo "$a : 字符串不为空"
    else
       echo "$a : 字符串为空"
    fi
    

    执行

    [root@centos6-1 ~]# ./helloworld.sh 
    abc = efg: a 不等于 b
    abc != efg : a 不等于 b
    -z abc : 字符串长度不为 0
    -n abc : 字符串长度不为 0
    abc : 字符串不为空
    [root@centos6-1 ~]# 
    

    5.文件测试运算符

    操作符 意义
    -b file 文件是否是块设备文件,如果是,则返回 true
    -c file 文件是否是字符设备文件,如果是,则返回 true
    -d file 是否是目录,如果是,则返回 true
    -f file 文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。
    -g file 文件是否设置了 SGID 位,如果是,则返回 true
    -k file 文件是否设置了粘着位(Sticky Bit),如果是,则返回 true
    -p file 文件是否是具名管道,如果是,则返回 true
    -u file 文件是否设置了 SUID 位,如果是,则返回 true
    -r file 文件是否可读,如果是,则返回 true
    -w file 文件是否可写,如果是,则返回 true
    -x file 文件是否可执行,如果是,则返回 true
    -s file 文件是否为空(文件大小是否大于0),不为空返回 true
    -e file 文件(包括目录)是否存在,如果是,则返回 true

    下面是详细例子

    #!/bin/bash
    
    file="/com/zaomianbao"
    if [ -r $file ]
    then
       echo "文件可读"
    else
       echo "文件不可读"
    fi
    if [ -w $file ]
    then
       echo "文件可写"
    else
       echo "文件不可写"
    fi
    if [ -x $file ]
    then
       echo "文件可执行"
    else
       echo "文件不可执行"
    fi
    if [ -f $file ]
    then
       echo "文件为普通文件"
    else
       echo "文件为特殊文件"
    fi
    if [ -d $file ]
    then
       echo "文件是个目录"
    else
       echo "文件不是个目录"
    fi
    if [ -s $file ]
    then
       echo "文件不为空"
    else
       echo "文件为空"
    fi
    if [ -e $file ]
    then
       echo "文件存在"
    else
       echo "文件不存在"
    fi
    

    执行

    [root@centos6-1 ~]# ./helloworld.sh 
    文件不可读
    文件不可写
    文件不可执行
    文件为特殊文件
    文件不是个目录
    文件为空
    文件不存在
    [root@centos6-1 ~]# 
    

    十一.流程控制

    1.if-else

    
    if condition
    then
        //做你想做的事
    else
        //做你想做的事
    fi
    
    
    if condition1
    then
        //做你想做的事
    elif condition2 
    then 
        //做你想做的事
    else
        //做你想做的事
    fi
    

    2.case

    case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令

    case 值 in
    模式1)
        //做你想做的事
        ;;
    模式2)
        //做你想做的事
        ;;
    *)
        //做你想做的事
        ;;
    esac
    

    取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。匹配发现取值符合某一模式后,其间所有命令开始执行直至 ;;。;; 与其他语言中的 break 类似,意思是跳到整个 case 语句的最后。取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。

    3.for

    for 变量 in 列表
    do
        //做你想做的事
    done
    

    4.while

    while command
    do
       //做你想做的是
    done
    

    5.until

    until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。一般while循环优于until循环,但在某些时候,也只是极少数情况下,until 循环更加有用。

    until command
    do
       //做你想做的事
    done
    

    command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

    十二.函数

    函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高。像其他编程语言一样,Shell 也支持函数。Shell 函数必须先定义后使用。

    #!/bin/bash
    
    demoFun(){
        echo "这是我的第一个 shell 函数!"
    }
    echo "-----函数开始执行-----"
    demoFun 
    echo "-----函数执行完毕-----"
    

    执行

    [root@centos6-1 ~]# ./helloworld.sh 
    -----函数开始执行-----
    这是我的第一个 shell 函数!
    -----函数执行完毕-----
    [root@centos6-1 ~]# 
    

    如果函数有返回值,则函数返回值可以在调用该函数后通过 $? 来获得。

    参考资料:
    https://baike.baidu.com/item/shell/99702?fr=aladdin
    http://www.runoob.com/linux/linux-shell.html
    https://www.cnblogs.com/maybe2030/p/5022595.html
    https://baike.baidu.com/item/POSIX/3792413?fr=aladdin

    展开全文
  • "$"后面引用的时系统变量,  比如 $USER   "&amp;"后面则是一个命令,  比如 echo &amp;date    
  • shell

    2019-09-16 20:22:38
    shell 什么是shell: 现在我们使用的操作系统(Windows、Mac OS、Android、iOS等)都是带图形界面的,简单直观,容易上手,对专业用户(程序员、网管等)和普通用户(家庭主妇、老年人等)都非常适用;计算机的普及...
  • shell-脚本入门

    2015-03-13 11:25:58
    1 Shell环境设置 1.1 登陆欢迎信息 终端机接口 (tty1 ~ tty6) 登陆的时候,会有几行提示的字符串,在 /etc/issue(附加信息可放置在/etc/motd)中定义。 issue 内的各代码意义: \d 本地端时间的
  • 一、shell基本知识 1. 什么是shell shell shell也是操作系统中的一个软件,它包在 linux 内核的外面,为用户和内核之间的交互提供了一个接口,系统中的命令用 shell 去解释 shell 接收系统回应的输出并...
  • 我们在shell 脚本编程中,经常需要用到字符串切割,即将字符串切割为一个数组,类似java 中的split 函数,下面对几种常见的方式做一个总结。目录方法一: 利用shell 中 变量 的字符串替换 方法二: 设置分隔符,...
  • shell编程中,经常需要将由特定分割符分割的字符串分割成数组,多数情况下我们首先会想到使用awk 但是实际上用shell自带的分割数组功能会更方便。假如 a=”one,two,three,four” 要将$a分割开,可以这样: OLD...
  • 说起函数调用,相信大家也不会陌生,然而对于初学Shell的我来说,Shell中函数调用方式却有点让我不太习惯,自己也走了不少的弯路,因为传递参数时出了一个很“自然”的错误,也让我吃了不少的苦头,所以总结一下...
  • 本文适合于想了解android系统基础知识,知道大家说的adb shell 到底是怎么回事儿的小白同学。 (主要偏向于windows用户,相信如果你用linux...本文可能已经帮不到你什么了) 一,从操作系统开始 windows、linux、...
  • #shell中对变量的值添加单引号,爽引号和不添加的区别:对类型来说是无关的,即不是添加了引号就变成了字符串类型, #单引号不对相关量进行替换,如不对$符号解释成变量引用,从而用对应变量的值替代,双引号则会...
  • Linux 中shell 脚本if判断多个条件格式如下,在比较时,数字和字符串用不同的比较符号 1.如果a&gt;b且a&lt;c if (( a &gt; b )) &amp;&amp; (( a &lt; c )) 或者 if [[ $a &gt; $b ...
  • 什么是shellshell编程

    2018-04-12 00:13:35
    1.什么是shellshell是你(用户)和Linux(或者更准确的说,是你和Linux内核)之间的接口程序。你在提示符下输入的每个命令都由shell先解释然后传给Linux内核。 说到底,Shell是用户与内核进行交互操作的一种接口...
1 2 3 4 5 ... 20
收藏数 1,116,168
精华内容 446,467
关键字:

shell