[hadoop@hadoop1 ~]$ date;who
Wed Apr 24 21:50:34 CST 2019
hadoop pts/1 2019-04-24 21:50 (172.24.37.64)
第一行指定要使用的shell
#!/bin/bash
分号与换行
单行语句一般要用到分号来区分代码块。当只有一个语句的时候,末尾无需分号,最后一个语句后面也无需分号。
双引号
放置到双引号中,而shell依然能够知道我们的意图
类型
shell脚本会自动决定变量值的数据类型。在脚本的整个生命周期里,shell脚本中定义的变量 会一直保持着它们的值,但在shell脚本结束时会被删除掉
变量每次被引用时,都会输出当前赋给它的值。重要的是要记住,引用一个变量值时需要使 用美元符,而引用变量来对其进行赋值时则不要使用美元符。
有两种方法可以将命令输出赋给变量:
[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。 在命令行提示符下运行脚本时一定要留心!
>
格式:command >
outputfile>>
格式:command >>
outputfile<
格式:command <
inputfile<<
) 格式:<<
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
将一个命令的输出重定向 到另一个命令中:
command1 | command2
在第一个命令产生输出的同时,输出会被立即送给第二个命令。数据 传输不会用到任何中间文件或缓冲区。
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语句)
函数
Linux提供了一个专门的变量$?
来保存上个已执行命令的退出状态码。对于需要进行检查的 命令,必须在其运行完毕后立刻查看或使用$?
变量。它的值会变成由shell所执行的最后一条命令的退出状态码。
[hadoop@hadoop1 test]$ date
Mon Apr 29 17:55:58 CST 2019
[hadoop@hadoop1 test]$ echo $?
0
按照惯例,一个成功结束的命令的退出状态码是0
。如果一个命令结束时有错误,退出状态码就是一个正数值。
无效命令会返回一个退出状态码127
。
默认情况下,shell脚本会以脚本中的最后一个命令的退出状态码退出。
#!/bin/bash
echo 123
exit 3
[hadoop@hadoop1 test]$ echo $?
3
格式:
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语句。
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
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
。
到目前为止,在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
命令可以判断三类条件:
大于号和小于号必须转义,否则shell会把它们当作重定向符号,把字符串值当作文件名。
3.文本比较
最后一类比较测试很有可能是shell编程中最为强大、也是用得最多的比较形式。它允许你测 试Linux文件系统上文件和目录的状态。
(暂时略)
if-then
语句允许你使用布尔逻辑来组合测试。有两种布尔运算符可用:
[ condition1 ]
&&
[ condition2 ]
[ condition1 ]
||
[ condition2 ]
示例1:
#!/bin/bash
if [ $1 -eq $2 ] && [ $3 -eq $4 ];then
echo both equal
else
echo other
fi
双括号命令允许你在比较过程中使用高级数学表达式。test命令只能在比较中使用简单的 算术操作。双括号命令提供了更多的数学符号。
格式:
(( expression ))
expression可以是任意的数学赋值或比较表达式。除了test命令使用的标准数学运算符,还有以下运算符。
可以在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
开头。
1. if
条件判断只能依据后边代码的退出码是否为0,退出吗0为真,非0为假。
2. 建议if test
直接用 if [ ]
格式。
3. if的几种格式:
if cmd
:判断cmd的返回码是否为0。如if pwd
if [ ]
: [ ]中为比较,数值比较用 -eq
等if (( ))
:(( ))中写数值表达式等。if [[ ]]
:单中括号的加强,可用模糊匹配。语法:
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