Linux命令行与shell脚本编程——第二部分shell脚本1

文章目录

  • 1. chapter11 构建基本脚本
    • 1.1 使用多个命令
    • 1.2 创建shell脚本文件
    • 1.3 命令替换
    • 1.4 重定向输入和输出
    • 1.5 管道
    • 1.6 数学运算
        • 浮点数解决方案
    • 1.7 查看退出状态码
        • exit
  • 2. chapter12 使用结构化命令
    • 2.1 if-then
    • 2.2 if-then-else
    • 2.3 if-elif
    • 2.4 test
    • 2.5 复合条件测试
    • 2.5 高级特性——双括号
      • 双小括号 (( ))
      • 双中括号 [[ ]]
    • if条件判断总结
    • 2.6 case

1. chapter11 构建基本脚本

1.1 使用多个命令

[hadoop@hadoop1 ~]$ date;who
Wed Apr 24 21:50:34 CST 2019
hadoop   pts/1        2019-04-24 21:50 (172.24.37.64)

1.2 创建shell脚本文件

第一行指定要使用的shell

#!/bin/bash

分号与换行

单行语句一般要用到分号来区分代码块。当只有一个语句的时候,末尾无需分号,最后一个语句后面也无需分号。

双引号

放置到双引号中,而shell依然能够知道我们的意图

类型

shell脚本会自动决定变量值的数据类型。在脚本的整个生命周期里,shell脚本中定义的变量 会一直保持着它们的值,但在shell脚本结束时会被删除掉

变量每次被引用时,都会输出当前赋给它的值。重要的是要记住,引用一个变量值时需要使 用美元符,而引用变量来对其进行赋值时则不要使用美元符。

1.3 命令替换

有两种方法可以将命令输出赋给变量:

  • 反引号字符(`)
  • $()格式
[hadoop@hadoop1 test]$ date
Mon Apr 29 15:29:57 CST 2019

# 方式1
[hadoop@hadoop1 test]$ test=`date`
[hadoop@hadoop1 test]$ echo $test
Mon Apr 29 15:30:03 CST 2019

#方式2
[hadoop@hadoop1 test]$ test=$(date)
[hadoop@hadoop1 test]$ echo $test
Mon Apr 29 15:34:04 CST 2019

注意,赋值等号和命令替换字符之间没有空格。

常见示例:

#!/bin/bash
# 以今天的日期生成文件
today=`date +%Y%m%d`
date +%y%m%d
ls /usr/bin > log.${today}

目录中出现的日志文件采用$today变量的值作为文件名的一部分。日志文件的内容是 /usr/bin目录内容的列表输出。

变量作用域

警告
命令替换会创建一个子shell来运行对应的命令子shell(subshell)是由运行该脚本的shell 所创建出来的一个独立的子shell(child shell)。正因如此,由该子shell所执行命令是无法使用脚本中所创建的变量的。 在命令行提示符下使用路径./运行命令的话,也会创建出子shell;要是运行命令的时候 不加入路径,就不会创建子shell。如果你使用的是内建的shell命令,并不会涉及子shell。 在命令行提示符下运行脚本时一定要留心!

1.4 重定向输入和输出

  1. 输出重定向:
    • 追加:> 格式:command > outputfile
    • 覆盖:>> 格式:command >> outputfile
  2. 输入重定向:
    • < 格式:command < inputfile
    • 其他:内联输入重定向符号是远小于号(<<) 格式:
      command << marker
      data
      marker

数据流向

一个简单的记忆方法就是:在命令行上,命令总是在左侧,而重定向符号“指向”数据流动 的方向。小于号说明数据正在从输入文件流向命令。

示例1:

[hadoop@hadoop1 test]$ date >> test1
[hadoop@hadoop1 test]$ cat test1
Mon Apr 29 16:48:28 CST 2019

示例2:

[hadoop@hadoop1 test]$ wc < test1
 1  6 29

wc命令可以对对数据中的文本进行计数。默认情况下,它会输出3个值:
 文本的行数
 文本的词数
 文本的字节数

内联输入重定向符号是远小于号(<<)。除了这个符号,你必须指定一个文本标记来划分输 入数据的开始和结尾。任何字符串都可作为文本标记,但在数据的开始和结尾文本标记必须一致。

示例3:

[hadoop@hadoop1 test]$ wc << EOF
> ;
> s
> ww
> EOF
3 3 7

1.5 管道

将一个命令的输出重定向 到另一个命令中:
command1 | command2

在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据 传输不会用到任何中间文件或缓冲区。

1.6 数学运算

  • expr操作(可以用2代替)
  • 使用方括号

bash shell为了保持跟Bourne shell的兼容而包含了expr命令,但它同样也提供了一种更简单 的方法来执行数学表达式。在bash中,在将一个数学运算结果赋给某个变量时,可以用美元符和 方括号($[ operation ])将数学表达式围起来。
用方括号执行shell数学运算比用expr命令方便很多。这种技术也适用于shell脚本。
示例1:

[hadoop@hadoop1 test]$ var1=5
[hadoop@hadoop1 test]$ var2=$[$var1*2]
[hadoop@hadoop1 test]$ echo $var2
10
[hadoop@hadoop1 test]$ var3=$[ $var1 * 3 ]
[hadoop@hadoop1 test]$ echo $var3
15

注意:上述并不能解决浮点数问题。只能处理整数。

浮点数解决方案

有几种解决方案能够克服bash中数学运算的整数限制。最常见的方案是用内建的bash计算器, 叫作bc。
bash计算器实际上是一种编程语言,它允许在命令行中输入浮点表达式,然后解释并计算该 表达式,最后返回结果。bash计算器能够识别:
 数字(整数和浮点数)
 变量(简单变量和数组)
 注释(以#或C语言中的/* */开始的行)  表达式
 编程语句(例如if-then语句)
 函数

1.7 查看退出状态码

Linux提供了一个专门的变量$?来保存上个已执行命令的退出状态码。对于需要进行检查的 命令,必须在其运行完毕后立刻查看或使用$?变量。它的值会变成由shell所执行的最后一条命令的退出状态码。

[hadoop@hadoop1 test]$ date
Mon Apr 29 17:55:58 CST 2019
[hadoop@hadoop1 test]$ echo $?
0

按照惯例,一个成功结束的命令的退出状态码是0。如果一个命令结束时有错误,退出状态码就是一个正数值。
无效命令会返回一个退出状态码127
Linux命令行与shell脚本编程——第二部分shell脚本1_第1张图片

exit

默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。

#!/bin/bash
echo 123
exit 3
[hadoop@hadoop1 test]$ echo $?
3

2. chapter12 使用结构化命令

2.1 if-then

格式:

if command 
then
commands
fi

变式:

if command ;then
commands
fi

bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码是0 (该命令成功运行),位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,then部分的命令就不会被执行,bash shell会继续执行脚本中的下一个命令。fi语句用来表示if-then 语句到此结束。

示例1:

#!/bin/bash
if pwd
then
echo this is if statement1
echo statement2
fi

结果:

[hadoop@hadoop1 if-then]$ sh if1.sh
/home/hadoop/test/if-then
this is if statement1
statement2

shell执行了if行中的pwd命令。由于退出状态码是0,它就又执行了then部分的echo语句。

2.2 if-then-else

if command
then
	commands
else
	commands
fi

示例1:

#!/bin/bash
var=$1
if [ $var -eq 1 ]
then echo 1
else echo 2
fi

传参为1则echo1,2则echo2,如下:

[hadoop@hadoop1 if-then]$ sh if2.sh 1
1
[hadoop@hadoop1 if-then]$ sh if2.sh 2
2

2.3 if-elif

if command1 
then
	command set 1 
elif command2
then
	command set 2
elif command3 
then
	command set 3 
elif command4 
then
	command set 4
fi

最后可加else或不加。

示例1:

#!/bin/bash
var=$1
if [ $var -eq 1 ]
then
    echo 1
elif [ $var -eq 2 ]
then
     echo 2
elif [ $var -eq 3 ]
then
    echo 3
else
    echo 'other'
fi

结果:

[hadoop@hadoop1 if-then]$ sh if3.sh 1
1
[hadoop@hadoop1 if-then]$ sh if3.sh 2
2
[hadoop@hadoop1 if-then]$ sh if3.sh 3
3
[hadoop@hadoop1 if-then]$ sh if3.sh 4
other

说明:if条件判断仅能判断if语句后边的退出状态码是否为0。

那么,上述if [ $var -eq 1 ]是怎么比较的呢?实际上用的是test

2.4 test

到目前为止,在if语句中看到的都是普通shell命令。你可能想问,if-then语句是否能测试命令退出状态码之外的条件。答案是不能。
但在bash shell中有个好用的工具可以帮你通过if-then语句测试其他条件。 test命令提供了在if-then语句中测试不同条件的途径。如果test命令中列出的条件成立,
test命令就会退出并返回退出状态码0。这样if-then语句就与其他编程语言中的if-then语句 以类似的方式工作了。如果条件不成立,test命令就会退出并返回非零的退出状态码,这使得 if-then语句不会再被执行。
test命令的格式非常简单。

test condition

condition是test命令要测试的一系列参数和值。当用在if-then语句中时,test命令看 起来是这样的。

if test condition 
then
commands
fi

变式:bash shell提供了另一种条件测试方法,无需在if-then语句中声明test命令。

if [ condition ] 
then
commands
fi

方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格,
否则就会报错。

示例1:测试是否有内容

#!/bin/bash
var="full"
if test  $var ;then
    echo this ok
else
    echo this other
fi

结果:

[hadoop@hadoop1 if-then]$ sh test1.sh
this ok

示例2:无内容(空串,即使空串中间有空格)时,为不成立

#!/bin/bash
var=" "
if test  $var ;then
    echo this ok
else
    echo this other
fi

结果:

[hadoop@hadoop1 if-then]$ sh test2.sh
this other

test命令可以判断三类条件:

  •  数值比较
  •  字符串比较
  •  文件比较

1.数值比较
Linux命令行与shell脚本编程——第二部分shell脚本1_第2张图片

2.字符串比较
Linux命令行与shell脚本编程——第二部分shell脚本1_第3张图片

大于号和小于号必须转义,否则shell会把它们当作重定向符号,把字符串值当作文件名。

3.文本比较

最后一类比较测试很有可能是shell编程中最为强大、也是用得最多的比较形式。它允许你测 试Linux文件系统上文件和目录的状态。
(暂时略)

2.5 复合条件测试

if-then语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用:

  • [ condition1 ] && [ condition2 ]
  • [ condition1 ] || [ condition2 ]

示例1:

#!/bin/bash
if [ $1 -eq $2 ] && [ $3 -eq $4  ];then
    echo both equal
else
    echo other
fi

2.5 高级特性——双括号

双小括号 (( ))

双括号命令允许你在比较过程中使用高级数学表达式。test命令只能在比较中使用简单的 算术操作。双括号命令提供了更多的数学符号。

格式:

(( expression ))

expression可以是任意的数学赋值或比较表达式。除了test命令使用的标准数学运算符,还有以下运算符。
Linux命令行与shell脚本编程——第二部分shell脚本1_第4张图片
可以在if语句中用双括号命令,也可以在脚本中的普通命令里使用来赋值。
注意,不需要将双括号中表达式里的大于号转义。这是双括号命令提供的另一个高级特性。

示例:

#!/bin/bash
v1=10
if (( $v1 ** 2 > 90 ));then
    (( v2=$v1 * 2 ))
    echo v2:$v2
else
    echo v1:$v1
fi

结果:

[hadoop@hadoop1 if-then]$ sh test4.sh
v2:20

双中括号 [[ ]]

双方括号命令提供了针对字符串比较的高级特性——模糊匹配。
格式:

[[ expression ]]

如:if [[ $USER == r* ]]表示$USER是否以r开头。

if条件判断总结

1. if条件判断只能依据后边代码的退出码是否为0,退出吗0为真,非0为假。
2. 建议if test 直接用 if [ ]格式。
3. if的几种格式:

  • if cmd:判断cmd的返回码是否为0。如if pwd
  • if [ ]: [ ]中为比较,数值比较用 -eq
  • if (( )):(( ))中写数值表达式等。
  • if [[ ]]:单中括号的加强,可用模糊匹配。

2.6 case

语法:

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac

示例:

#!/bin/bash
v=$1
case $v in
1 | 100)
echo 输入的是1或100的选项;;
a | b ) echo input string;;
*)
echo 其他;;
esac

结果:

[hadoop@hadoop1 if-then]$ sh case.sh
其他
[hadoop@hadoop1 if-then]$ sh case.sh 1
输入的是1或100的选项
[hadoop@hadoop1 if-then]$ sh case.sh a
input string

你可能感兴趣的:(shell,shell)