;
Bash script语法学习
(材料为bash reference manual)
3.1.2引用
简单来说就是通过一些操作让一些特殊字符原样输出,而不是被识别成指令或者变量值。
一些操作如下:
转义字符 \ :保留反斜杠(backslash)后跟的字符的字面意思,例如:echo "\"test\""输出”test”,因为双引号为特殊字符,要作为普通字符输出需要反斜杠转义。但有一个例外,反斜杠后跟回车代表新起一行,一般用于命令太长一行打不完,用这个可以在第二行接着打。
单引号:单引号里的内容保留其字面意义,两个单引号之间不能再用一个单引号,哪怕加了反斜杠。
双引号:双引号里大部分内容都按字面意义输出,有以下例外:$ ‘ \ ! 其中叹号只有在history expansion启用时才有特殊意义,这玩意我也不清楚,后面看到了再说。$代表引用变量值,单引号除啦上一段我还不知道有什么特殊的意义。反斜杠只有在后跟$、单引号、双引号、反斜杠、换行这几个特殊字符时才有特殊意义。例子:echo "\$\'\"\\\!" 输出为$\'"\\!
. 3.1.2.4 ANSI-C Quoting?
3.1.3 注释
第一行开头#后跟注释,不能打在命令后面。且注释能用只在以下几种情况:In a non-interactive shell, or an interactive shell in which the interactive_comments option to the shopt builtin is enabled
3.2.2管道以及3.6重定向以及文件描述符另开一篇
3.2.3
Cmd1 && cmd2 ,cmd1||cmd2 只有当cmd1返回0时才会执行第二个,整句的返回值为最后一个执行的命令的返回值。
3.2.4.1
三种循环结构,在讲这个之前,由于我不知道有没有自带的返回值几次执行后会从非零变到0的命令,所以为了可以测试这三个循环结构,我先写了一个简单的返回值从3到0循环变化的脚本,如下:
#!/bin/bash
#read var file,assign the value to the var1
while read line
do
var1=$line
done < var
#delete after read,the arguments -i is necessary,or else it will not be effective,
#only print the result without change the file
sed -i '/'"$var1"'/d' var
let var1--
#be cautious that the space is necessary
if [ "$var1" = "-1" ];then
var1=3
fi
#write the var1 to the var file
echo "$var1" >> var
echo $var1
exit $var1
该文件置于家目录的bin下,同时新建一个文本文件var,输入3保存即可。这个脚本就是读取文件里的数字赋给var1变量,删除文件里的这个数字,var1变量--,写回文件中,若这个变量为-1,重新赋值为3,最后返回var1。效果就是每执行一次输出一个数,返回值也是这个数,值从3到0循环变化。
接下来简单讲三个循环结构
#test-commands非零时执行do后面的命令,整个语句返回值为最后一个被执行的consequent-commands返回值,若没有被执行过则返回0
until test-commands;
do consequent-commands
done
以下为测试效果,test1.sh为之前的脚本,test2如下
#!/bin/bash
until test1.sh;
do echo "untilDo"
done
exit 0
#test-commands为零时执行do后面的命令,整个语句返回值为最后一个被执行的consequent-commands返回值,若没有被执行过则返回0
while test-commands
do consequent-commands
done
以下为测试
#!/bin/bash
while test1.sh
do echo "untilDo"
done
exit 0
先将var的值调为1,执行test2.sh,结果如下
For循环,有两种形式,先说更符合c的一种,如下
for (( expr1 ; expr2 ; expr3 ))
do commands
done
开始时,expr1被执行,接着expr2值若为非零,执行commands后执行expr3,再检查expr的值,如此往复,若3个式子有一个或多个省略,默认为1,返回值为最后执行的commands的值,若没有被执行,返回false。
例子如下
#!/bin/bash
for (( i=1 ; i<3 ; i++ ))
do echo "forDo"
done
exit 0
输出:
再看另一个例子
#!/bin/bash
test1.sh
var1=$?
for (( ;var1; ))
do echo "forDo"
test1.sh
var1=$?
done
exit 0
test1就是之前写的那个,$?可以获得上次执行的命令的返回值,注意这个for里能放的只能是表达式,不像之前两个循环结构,我放命令在for里会有语法错误。输出如下
再说说for的第二种形式
for 变量 in 值1 值2 值3…
do
程序
done
变量分别被赋为值1 值2 ….,每赋值一次执行一次后面的程序,有几个值就循环几次,例子如下
#!/bin/bash
for t in 1 2 3
do echo "t:$t"
done
exit 0
输出
还有一种用法,涉及到后面的知识,所以只是在这记录下
for t
do echo "t:$t"
done
exit 0
输出
分支结构
if test-commands
then consequent-commands
elif more-test-commands
then more-consequents;
else alternate-consequents;
fi
为0为真,执行对应if后面的语句,最后的else执行条件为,前面所有语句均不符合条件(返回值不为零)
以下为test2.sh
#!/bin/bash
if test1.sh
then echo "if-1"
elif test1.sh
then echo "if-2"
else echo "if-3"
fi
exit 0
几组测试如下
Case语句语法
case $var in
var1 | var2 )
Cmd1
;;
var3)
Cmd2
;;
*)
Cmd3
;;
Esac
根据var变量,选择一致的分支,执行对应指令,若都不符合则执行最后的指令
测试代码如下
#!/bin/bash
test1.sh
var=$?
case $var in
1 | 2)
echo "1 or 2"
;;
3)
echo "3"
;;
*)
echo "*"
;;
esac
exit 0
输出如下
select 语句
select表达式是bash的一种扩展应用,擅长于交互式场合。用户可以从一组不同的值中进行选择:
select var in ... ; do
break;
done
.... now $var can be used ....
下面是一个简单的示例:
#!/bin/bash
echo "What is your favourite OS?"
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
break;
done
echo "You have selected $var"
该脚本的运行结果如下:
What is your favourite OS?
1) Linux
2) Gnu Hurd
3) Free BSD
4) Other
#? 1
You have selected Linux
关于(( )):If the value of the expression is non-zero, the return status is 0; otherwise the return status is 1. This is exactly equivalent to let "expression" 实例如下
3.2.4.2关于[[ ]] 太长了 先跳过
3.2.4.3 ()和{}的作用是将几个指令作为一个整体执行,以下为使用的实例
Dir1和dir2中分别有2个和一个文件,若要统计的是这两个目录下文件的总数,可以用如下方法。
两个均可以,wc -l统计行数,wc -w统计单词数,这里注意,第一个ls虽然输出是两个一行的文件名,但是应该是显示的时候对ls的输出做了处理,实际上,把ls输出重定向到文件再用cat显示,它是有换行的,所以统计行数为2
有几点注意可以提一下。
可见,( )的内容是在子shell中执行的,所以变量更改没有生效,另外,使用{ }时,大括号旁的空格和最后一个命令的分号都不能少。
3.2.5 没看懂,跳过
3.2.6简单介绍了下GNU Parallel,这是一个能实现任务并行处理的工具,暂时用不到,就先跳过了。
3.3shell函数,我个人理解就是把一段命令取了个名字,调用这段命令就变得简便一些。