本文最后更新于 2024-10-31,文章距离上次更新已超30天,内容可能有些老了——

用shell直接写的文件脚本,以.sh为后缀

在开头要注明解释器为bash (或者直接用bash xxx 来运行...带是加上这句注释后,就可以直接./来运行)

#! /bin/bash 

#上面那句表明这个文件的解释器是bash,写每一个sh文件开头都需要加上

#single comment

:<<EOF

多行

注释

EOF 

echo "hello world !"
echo '如果使用单引号,则不会\\" 转义。也用不了${变量}这样的,只会原样输出'

name="我是一个变量,注意等号两边不能有空格,否则会报错"

echo "文件名:"$0
echo "输入的第一个参数:"$1
echo "输入的第二个参数:"$2
echo "输入的第三个参数:"$3
echo "参数总数:"$#

echo "输出所有参数:"$*
echo "我也是输出所有参数"$@

echo "当前进程:"$$
echo "输出该条命令的标准输出:" $() " 或者:" `在(``)中写命令`
echo "输出上一条命令的exit code :"$?

echo $(expr length "$name") #使用expr表达式,注意是$(),不是${}.前者执行命令,后者输出变量
echo `expr length ${name}` #和上一句等效

#expr 会有一个自己的输出(stdout) ,同时也有一个exit code。当**逻辑表达式**中,expr中stdout结果为真,exit code 则为0,反之为1
# stdout 中的 1  对标exit code 中的 0.

a=1                                                                               
b=2                                                                              
echo $(expr \\( $a + 2 \\) \\* \\( $b + 3 \\))                                        
:<<aaa                                                                            
expr中每一个命令之间都必须加上空格。上述命令等价于(a+2)*(b+3)-                    
可以先理解为对命令中每两个字符之间加上空格,然后在需要转义的地方加上转义         
...注意变量要用$标识。                                                           
其中,*,还有小括号这些,都需要加上转义字符才能进行输出                          
aaa  

关于expr ,可以有另一种方法进行计算
echo $((a+b)) 通过$(( )) 来将内部内容直接计算。
双括号中间的变量不需要加上$,直接计算即可。 
#! /bin/bash

read -p "加上-p后,后面一句可以写注释,用于提示用户输入" -t 5 name

echo "-t表示等待时间,最后输入的name是变量,值为${name}"

printf "也可以在bash中使用printf语句,方法同c,不过不用逗号,而是用空格隔开 %s\\n" ${name}

test 用于判断,后面可以接判断语句
test 2 -lt 3 #判断2小于3,输出为真(0)
# 由于test 返回的是exit code ,在程序中,返回exit code 为0,默认为程序正常执行。(相当于c等语言main函数最后return 0)

test -e someFile.sh && echo "Exist" || echo "Not Exist"
#可以实现类似三目运算符的功能。因为&&与||存在短路原则,&&前面为假,则后面语句不执行。||前面为真,则后面语句不执行
test -s 判断该文件是否为空...此外test还有很多其他参数,比如-r 判断是否可读,-f 判断是否是文件等
具体使用时,可以即使查文档 man test

[ -e new1.sh ] && echo "Exist" || echo "NOT Exist"
#使用 [] 可以实现和test几乎相同的功能,注意[] 开头结尾都需要加上空格

#使用这些的时候,如果用到了变量,最好用""将变量括起来,否则如果变量中出现了空格的时候,容易产生问题

#条件判断,每个if,elif后面都要有个then。这里condition通常使用[ ]
if condition1
then 
	xxxx
elif 
then 
	xxxx
else
	xxxx
fi #表明判断语句结束,需要在最后写上fi(是if反过来写的)

#case判断,对标c中的switch

case ${变量名} in
	值1)
		xxxx
		;; #类似于break;
	值2)
		xxxx
		;;
	*)   #类似于default
		xxxx
		;; 
esac
for var in val1 val2 val3
do 
	xxxx
	xxxx
done
#in 后面直接写几个单词,则按这几个单词为变量依次循环
# `ls` 这种语句运行,则按照语句的输出(stdout)依次输出。
#可以使用 $(seq 1 10) 或者 {1..10} 来输出从1到10 {a..z}也可以输出a~z

#for 语句既可以按照上面那种类似python中的写法,也可以按照c++的语法
for((...;...;...)) #注意这里是两个括号
do
	xxxx
done

while condition
do
	xxxx
done

until condition #功能类似于while,但是只在条件为真的时候才结束。
do 
	xxxx
done 

break 跳出当前一层循环(不适用于case 命令)
continue 跳出本轮循环。功能同c++等语言的。
#! /bin/bash
[function] func_name(){
	xxxx
	...
}
#[function] 可以省略

对于shell/bash中的函数,return值是exit code,而不是标准输出stdout
如果要获得标准输出,可以通过echo $(func_name) 的形式实现
return 值可以通过$?获得(其实就是获取exit code 的方式)
也可以自定义return 的值。 

exit 命令可以用于退出当前进程,并且返回一个退出状态exit code
可以用$?来获取该退出状态。可以定义0~255之间的整数。但是只有0才会被认为是正常退出,表示成功。

#文件重定向
command > file 将内容输出到file中(覆盖
command >> file 将内容追加输出到file中(不会覆盖原有的
command < file 将file中的内容作为输入。
在同一行中,可以同时实现输入和输出重定向。

在sh文件中,可以使用:
n=$(<"xxx")来将xxx文件中的内容输入到变量n中
echo/cat $n > "xxx" 将n中的内容输出到xxx文件中

#引入外部脚本,在该文件开头写上:
. filename
或者
source filename 
:<<EOF
实际上实现的是将filename中的内容全部在当前文件中展开
所以filename中的所有语句在当前文件中都会被再实现一次。
EOF