Shell语法
Shell
命令
ls = list
cd = change directory
cp = copy
mv = move
rm = remove
ps = process status
pwd = print work directory
du = disk usage
df = disk free
mkdir = make directory
rmdir = remove directory
su = switch user
chown = change owner
chmod = change mode
参数
-a = all
-l = list
-f = force
-n = number
-u = user
-z = zip
which python3 = 查看库依赖的路径
env = 查看环境变量
- 关于
shell
shell
本身是一个进程,shell
命令也会产生其他进程(除shell
内建命令外)。调用shell内建命令相当于调用shell
进程中的一个函数,并不创建新的进程。凡是which
命令查不到程序文件所在位置的命令都是内建函数。或者:
man bash-builtins
- 查看shell类型
echo $SHELL
查看passwd文件用户的启动和命令
- 执行脚本
cmdTest.sh
#!/bin/sh - 注释,指定是shell脚本 echo "hello world" - 在屏幕上输出hello world cd .. ls
chmod a+x cmdTest.sh
./cmdTest.sh
执行之前需要改变文件可执行权限,执行该脚本相当于新建一个进程,但是当前工作的路径不会改变
cmdTest.py
#!/usr/bin/python3 if __name__ == '__main__': print("hello world")
chmod a+x cmdTest.py
./cmdTest.py
执行:
./test.sh
/bin/sh test.sh
(cd..; ls -l)
source test.h
变量命名:基本和C语言命名变量一样
赋值:等号前后不能有空格,否则会被当成一个命令和被执行两个的文件
使用变量:
$varname
${varname}
使用{}
是为了区分类似于a
和aa
这种变量。
变量测试
varTest.sh
#!/bin/bash globalvar1="hello" function test(){ globalvar2="world" } #调用函数 test echo $globalvar1 $globalvar2
除非变量名前面加上local
等限定词,不管是函数内部还是外面都默认为全局变量。该进程中还可以嵌套其他的脚本,在执行的时候会另开一个进程,这些变量不会跨进程,只是单纯的另开一个新的进程。除非是source ./subScripe.sh
或者是环境变量export
限定。局部变量只能定义在函数内部
环境变量
每一个进程中都有系统下的参数,当启动一个子进程,父进程的环境变量会拷贝到子进程中,但仅仅是拷贝,在子进程中修改环境变量之后返回父进程,父进程中该环境变量不会改变。即环境变量可以跨进程,但是是单向传递。
删除变量:相当于置空
uset varname
通配符*
、?
、[]
ls ~/*.test.txt
dirTest.c
#include <stdio.h> int main(int argc, char **argv ) { for(int i = 0; i < argc; ++i){ printf("argv[%d]:%s\n", i, argv[i]); } return 0; }
touch 1.txt 2.txt 3.txt
touch {1,2,3}.txt
./a.out *.txt
./a.out [1-3].txt
./a.out {1..3}.txt
输出
$ argv[0]:./a.out
$ argv[1]:1.txt
$ argv[2]:2.txt
$ argv[3]:3.txt
代换成功的前提是存在。
- 命令代换:
DATE=`date` - 反引号
DATE=$(data) - $()
test.sh
#!/bin/bash datetime=`date` echo "date is : " $datetime
执行的命令也是在当前文件夹下,所以不同的文件夹下执行可能是不同的。
算数代换
使用$(())
用于算数运算,(())
中的shell变量取值将转换成整数,或者$[]
var=45
echo $(($var + 3)) #等价于$((var+3)) 或 echo $[var+3]或$[$var+3]
注意:$(())
中只能使用+-*/
和()
运算符,并且==只能做整数运算==。
进制转换
$[base#n]
其中base
表示进制,n按照base进行解释,,后面再有运算数,按十进制解释。
echo $[8#10+11] #将10以8进制来解析,得到的是10进制的8,加上11---》19
echo $[16#10+11]
转义字符
反斜杠\
表示后面取字面值,相当于后面就是字符串而不是什么变量
echo $SHELL
/bin/bash
echo \$SHELL
$SHELL
创建一个$ $
的dir
mkdir \$\ $
创建一个带-
的文件:加上当前的路径,但不建议。
touch ./-hello
单引号:保持字符串的字面值,即便有特殊符号。
C中单引号是字符,Shell脚本中的单引号和双引号都是字符串的界定符,而不是字符的界定符。
echo 'aaaa' # 输出aaaa
echo 'aaaa
>bbbb'
# 输出
aaaa
bbbb
双引号经常作为参数
var="a b"
touch $var # 创建两个文件
touch "$var" # 创建一个文件
有些文件名中间存在空格
使用变量之前,如果变量是作为一个参数来传递,应该要习惯性加上双引号。
算术代换:最基本的整数运算
var=45
$[45+1]
$((var+3))
变量的分类
Shell内变量:在Shell解析环境中存在变量
默认全都是全局变量,作用域和生命周期都是到整个脚本结束
局部变量:使用local修饰,只能声明在函数内部
Shell内变量只能在当前Shell进程中使用,跨进程不能使用
环境变量:子进程会拷贝父进程的环境变量,单向传递
export varname=value
或者:
varname=val;``export varname;
文件名替换
*
匹配0个或多个任意字符
?
匹配任意一个字符
[若干字符]
匹配方括号中任意一个字符的一次出现
参数拓展
touch 1.txt 2.txt 3.txt 4.txt
touch {1,2,3,4}.txt
touch {1..4}.txt
touch {1..4}_{5..6}.txt
命令代换
执行某一条命令,将这个命令的标准输出的内容存到某个变量
varname=`cmd arg1 arg2`
$(cmd)和`cmd`等价
条件测试
使用test或者[可以测试一条语句是否为真,真的返回值为0
var=2
test $var -gt 1 #检测var变量是否greater than 1
echo $? #显示上一条命令的执行结果 ---》1
[ $var -gt 3 ] #和上述test语句一样
echo $? #---》0 n
[ EXPRESION ]
! EXPRESION #取反
EXPRESION1 -a EXPRESION2 #逻辑与
EXPRESION1 -o EXPRESION2 #逻辑或
-n STRING #判断字符串不是空串
-z STRING #判断字符串长度为0
STRING1 != STRING2 #判断字符串是否相等
STRING1 = STRING2 #判断字符串相等
INTEGER1 -eq INTEGER2 #判断整数相等
INTEGER1 -ge INTEGER2 #判断greater equal
INTEGER1 -le INTEGER2
INTEGER1 -lt INTEGER2
INTEGER1 -ne INTEGER2
文件
FILE1 -nt FILE2 #new than
FILE1 -ot FILE2 #old than
-b FILE #块设备
-c FILE #字符设备
-d FILE #目录
-e FILE #是否存在
-f FILE #普通文件
-s FILE #存在且大小大于0字节
-S FILE #是socket文件
-r FILE #有读权限
-w FILE #有写权限
-x FILE #可执行权限
if分支语句
if 命令1|条件测试1
then
xxxxx
elif 命令2|条件测试2;then #
xxxxx
else #else不用加then
xxxxx
fi
#!/bin/bash
if [ -f /bin/bash ]
then
echo "/bin/bash is a file"
else
echo "/bin/bash is not a file"
fi
if :
then
echo "always true"
fi
#!/bin/bash
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
if [ "$YES_OR_NO" = "yes" ]
then
echo "Good morning!"
elif ["$YES_OR_NO" = "no" ]; then
echo "Good afternoon!"
else
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
fi
# 如果make命令失败就不会执行后面的sudo make install
make && sudo make install
# 如果前面的命令执行失败,就执行后面的命令
echo xxx || exit 1
#!/bin/bash
var=1
var2=2
if [ $var -eq $var2 ] && [ $var2 -eq 2 ]
then
echo "yes"
else
echo "no"
fi
特殊变量
$0 # 相当于C语言的main函数的argv[0]
$1、$2... # 相当于C语言中的 argv[1]、argv[2]
$# # argc - 1
$* # 表示参数列表 $1 $2
$? # 上一条命令的退出状态
$$ # 当前进程号
for循环
#!/bin/bash
for FRUIT in apple banana pear
do
echo "I like $FRUIT"
done
sum=0
for i in {1..100}
do
sum=$[$sum+$i]
done
echo $sum
case命令
#!/bin/bash
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
case "$YES_OR_NO" in
yes|y|Yes|YES)
echo "Good Morning!";;
[nN][oO])
echo "Good Afternoon!";;
*)
echo "Sorry,$YES_OR_NO not recognized. Enter yes or no.";;
esac
case 表达式 in
val1|pattern1)
xxxxx
;;
val2|pattern2)
xxxxx
;;
*)
xxxxx
;;
esac
while循环
#!/bin/bash
echo "Enter password:"
read TRY
while [ "$TRY" != "8520" ]
do
echo "Sorry, try again"
read TRY
done
输入输出
echo [option] string
-n #表示不换行
-e #解析转义字符
echo -e "hello\tworld"
管道
通过|把一个命令的输出传递给另一个命令做输入
cat myfile | more
df -k
tee命令
tee命令把结果输出到标准输出
ls | tee a.txt #把ls的结果输入到a.txt
ls | tee -a a.txt #把ls的结果追加到a.txt
文件重定向
cmd > file #标准输出重定向到file
cmd >> file #标准输出追加到file
cmd < file1 > file2 #输入输出都定向到文件里
#include <stdio.h>
#include <ctype.h>
int main()
{
int ch = getchar();
while (ch != EOF) {
putchar(toupper(ch));
ch = getchar();
}
return 0;
}
gcc main.c -o upper
cat main.c | ./upper | tee upper.txt
函数
function 函数名() { #function 和 ()至少保留一个
local var=value
return 1; #只能返回整数
}
#!/bin/bash
text (){
echo "test"
return 1;
}
text
echo $?
function text2 {
echo "aaaa"
return 0
}
var=`text2`
echo $var
#!/bin/bash
function visit {
dir="$1"
for f in `ls $1`
do
if [ -f "$f" ]
then
echo "$f is a file"
elif [ -d "$f" ]
then
echo "$f is a dir"
visit "$f"
else
echo "$f is not recognized."
fi
done
}
visit
脚本调试
-n 遍历一个脚本,检查语法错误
-v 一边执行脚本一边解析到脚本的输出
-x 执行脚本的同时打印每一句指令
打开调试方法
bash -x 脚本.sh
脚本开头 #!/bin/bash -x
正则表达式
1.以S开头的字符串
^S #^表示开始, $表示结束
2.以数字结尾的字符串
[0..9]
\d
[0123456789]
[1-9]$ # $匹配最后一个字符
3.匹配空串
^$
4.字符串只包含三个数字
^\d\d\d$
^\d{3}$ # {n}表示前面的单元重复n次
5.字符串中只有3到5个字母
控制最少重复次数和最大重复次数
{m,n} # m表示前面单元重复最少的次数,n表示前面单元重复的最大次数
[a-zA-Z] # 表示大小写字母
^[a-zA-Z]{3,5}$
6.匹配不是a-z的任意字符
[^a-z] #中括号中第一个字符如果是^,表示区间取反
^[^a-z]$
7.字符串只有0到1个数字或者字母或者下划线
{0,1} #表示重复0到1次
? #也可以表示0到1次的重复
^[a-z_A-Z0-9]?$
^\w?$
8.字符串有一个或者多个空白字符(\t\n\r等)
^\s{1,}$
^\s+$
9.字符串有0个或者若干个任意字符(除了\n)
. #表示任意字符,除了\n
? #0-1
+ #1-n
* #0-n
^.{,}$
^.*$ # *表示前面的单元重复0到n次
10.匹配0或者任意多组ABC、比如ABC,ABCABC
使用小括号来将多个单元重新组合成为一个单元
^(ABC)*$
11.字符串要么是123要么是ABC
| 表示选择两边的正则匹配其中一个
^ABC|123$
^(ABC|123)$
12.字符串只有一个点号
^\.$
13.匹配十进制数的三位整数
^[1-9][0-9][0-9]$
^[1-9][0-9]{2}$
14.匹配0-255的整数
基础的正则:+?*是普通字符
扩展的正则:+?*是特殊字符
perl的正则: