数组¶
定义一个数组变量¶
range¶
语法:
{start..end..step}
示例:
# 输出 1 2 3
for value in {1..3}
do
echo $value
done
# 输出 1 3 5
for value in {1..6..2}
do
echo $value
done
if¶
if 语句的语法如下:
if [ <some test> ]
then
<commands>
elif [ <some test> ]
then
<different commands>
else
<other commands>
fi
比如:
if [ "$age" -gt 18 ]
then
echo "you are $age > 18"
elif [ "$age" -eq 18 ]
then
echo "you are $age == 18"
else
echo "you are $age < 18"
fi
常用的条件判断¶
条件表达式 | 含义 |
---|---|
! 表达式 | false |
-n 字符串 | 字符串长度大于 0 |
-z 字符串 | 字符串长度等于 0 |
A = B | 字符串 A B 相等 |
A != B | 字符串 A B 不相等 |
m -eq n | 数字 m n 相等 |
m -gt n | 数字 m 大于 n |
m -lt n | 数字 m 小于 n |
-d 路径 | 文件路径存在,并且是个目录 |
-e 路径 | 文件存在 |
-s 路径 | 文件存在,并且大小大于 0 |
-r 路径 | 文件存在,并且拥有读权限 |
-w 路径 | 文件存在,并且拥有写权限 |
-x 路径 | 文件存在,并且拥有执行权限 |
[] 实际调用的是 test 命令,我们可以用 test 命令来测试条件表达式:
$ test "abc" == 18
$ echo $?
1
$ test 1 -eq 1
$ echo $?
0
以及可以用 && 和 || 组合判断多个条件表达式,实现 and 和 or 的功能
case(switch case)¶
语法:
case <variable> in
<pattern 1>)
<commands>
;;
<pattern 2>)
<other commands>
;;
esac
例子:
case $1 in
start)
echo starting
;;
stop)
echo stoping
;;
restart)
echo restarting
;;
*)
echo don\'t know
;;
esac
for¶
语法:
for var in <list>
do
<commands>
done
同时 for 也支持 break 和 continue
例子:
names='tom jim jake'
for name in $names
do
echo $name
done
for age in {1..10}
do
if [ $age -eq 3 ]
then
continue
fi
echo $age
if [ $age -gt 5 ]
then
break
fi
done
while¶
语法:
while [ <some test> ]
do
<commands>
done
例子:
total=1
while [ $total -le 3 ]
do
echo $total
((total++))
done
until¶
语法:
until [ <some test> ]
do
<commands>
done
例子:
total=1
until [ $total -gt 3 ]
do
echo $total
((total++))
done
select 单项选择¶
选择功能一般用 case 语法用的多,不过 select 也可以实现, select 的功能类似 while + case,比较适合反复询问用户选择项直到用户选择了输入了合法的选择项。
语法:
select var in <list>
do
<commands>
[break]
done
可以用 break 跳出 select 以及可以通过修改 PS3 变量的值修改提示内容。
示例:
PS3='please choice: '
select value in {1..5}
do
echo $value
if [ $value -gt 3 ]
then
break
fi
done
函数¶
语法:
function_name () {
<commands>
}
# or
function function_name {
<commands>
}
参数¶
在函数体内可以通过 $1, $2, $3, ... 获取调用时传入的位置参数
变量作用域¶
默认函数类的变量是全局变量,可以通过 local 定义局部变量:
function test {
local a='local'
a='233'
b='666'
echo $a, $b
}
b='global'
test
echo $b
echo $a
创建跟外部命令同名的函数¶
例子:
function ls {
command ls -lh
}
ls
主要是不要忘了加 command,不加的话,上面的 ls 会无限递归不会按预期的调用 ls 命令。
字符串操作¶
字符串替换¶
替换子串¶
$ test="hello_world"
$ echo "${test/_/-}"
hello-world
$ echo "${test/world/bar}"
hello_bar
删除前缀¶
$ test="foofoo_bar_foofoo"
$ echo "${test#foo}"
foo_bar_foofoo
$ prefix="foo"
$ echo "${test#$prefix}"
foo_bar_foofoo
删除后缀¶
$ test="foofoo_bar_foofoo"
$ echo "${test%foo}"
foofoo_bar_foo
$ suffix="foo"
$ echo "${test%$suffix}"
foofoo_bar_foo
文件操作¶
保存大段文本¶
可以使用 tee 和 EOF:
tee test.text <<EOF
hello
world
!
EOF
保存包含 EOF 命令的文本可以用多个 EOF 的变种:
tee a.sh << EOF
tee b.text << EOF2
echo hello
EOF2
EOF
$ tee a.sh << EOF
> tee b.text << EOF2
> echo hello
> EOF2
> EOF
tee b.text << EOF2
echo hello
EOF2
$ cat a.sh
tee b.text << EOF2
echo hello
EOF2
$ bash a.sh
echo hello
$ cat b.text
echo hello
append 更新可以使用 tee -a
其他实用功能¶
隔离 cd 命令的干扰
可以用括号来隔离:
# pwd=/tmp
(
cd test/
ls # pwd = /tmp/test/
)
# pwd=/tmp
设置功能标志¶
一般会在脚本中设置如下标志:
set -euo pipefail
IFS=$'\n\t'
常用的功能标志如下:
- 运行的时候显示执行到那一条语句了: set -x
$ cat a.sh
set -x
echo 'hello'
$ bash a.sh
+ echo hello
hello
bash -x xx.sh 也可以实现同样的效果:
$ cat a.sh
echo 'hello'
$ bash -x a.sh
+ echo hello
hello
- 有任何命令的退出码不是 0 就退出: set -e
$ cat a.sh
abc
echo 'hello'
$ bash a.sh
a.sh: line 1: abc: command not found
hello
$ cat a.sh
set -e
abc
echo 'hello'
$ bash a.sh
a.sh: line 2: abc: command not found
bash -e xx.sh 也可以实现同样的效果。
- 引用未定义的变量时出错并退出: set -u
$ cat a.sh
echo "$abc"
echo hello
$ bash a.sh
hello
$ cat a.sh
set -u
echo "$abc"
echo hello
$ bash a.sh
a.sh: line 2: abc: unbound variable
bash -u xx.sh 也可以实现同样的效果。
- 管道命令中有一个命令失败整个管道操作的退出码将是失败的那个命令的退出码, 未设置这个标志时是最后一个操作的退出码: set -o pipefail
$ cat a.sh
la la la | echo 'aa'
$ bash a.sh
a.sh: line 1: la: command not found
aa
$ echo $?
0
$ cat a.sh
set -o pipefail
la la la | echo 'aa'
$ bash a.sh
a.sh: line 2: la: command not found
aa
$ echo $?
127
- 设置单词切分使用的分隔符,默认是 $' \n\t' (空格、换行、制表符), 可以通过 IFS=$'\n\t' 设置为换行和制表符:
$ cat a.sh
names=(
"foo bar"
"foobar tom"
)
for i in ${names[@]}; do
echo "$i"
done
$ bash a.sh
foo
bar
foobar
tom
$ cat a.sh
names=(
"foo bar"
"foobar tom"
)
IFS=$'\n\t'
for i in ${names[@]}; do
echo "$i"
done
$ bash a.sh
foo bar
foobar tom
更多的 set 支持的标志可以查看 Bash Reference Manual
数学运算¶
可以通过 $(( <expression> )) 执行数学运算,比如:
- +: $(( 1 + 2 ))
- -: $(( 1 - 2 ))
- *: $(( 1 * 2 ))
- /: $(( 1 / 2 ))
- %: $(( 1 % 2 ))
支持变量做运算符,比如: $(( a + b )) (推荐) 或 $(( $a + $b )) (不推荐, 详见 SC2004 - shellcheck )
Comments