Shell 基本操作总结

5 minute

shell 参数

  • $# 参数个数
  • $@ / $* 取出所有参数
  • $0 取出命令中第一个字符串
  • $1 取出第一个参数
1if [ "$1" == "-u" ]
2then
3    echo update
4fi
5echo $0

ans:

1[root => ~]$ ./test.sh
2./test.sh
3[root => ~]$ ./test.sh -u
4update
5./test.sh

$@$* 的区别:(from stackoverflow

$@ behaves like $* except that when quoted the arguments are broken up properly if there are spaces in them.

Take this script for example (taken from the linked answer):

1for var in "$@"
2do
3    echo "$var"
4done

Gives this:

1$ sh test.sh 1 2 '3 4'
21
32
43 4

Now change $@ to $*, And you get this:

1$ sh test.sh 1 2 '3 4'
21
32
43
54

个人觉得使用 $@ 更为妥当。

关于数组

取值

根据下标取值,下标从 0 开始:

1${arr[0]}
2${arr[1]}
3${arr[2]}

获取所有值:

1${arr[@]}
2
3# 常用于:
4/bin/bash test.sh ${arr[@]}

获取长度:

1${#args[@]}
2
3if [ ${#args[@]} -eq 0 ]; then
4	echo "length=0"
5fi

切片

数组切片:

1# 从 $start 开始到 $end
2arr=( $(arr[@]:$start:$end) )
3
4# 从 $start 开始到最后,两侧必须加括号
5arr=( $(arr[@]:$start) )

一个简单的测试:

 1root@Server-Debian-Jzh:~# arr=(1, 2, 3, 4, 5)
 2root@Server-Debian-Jzh:~# echo ${arr[@]}
 31, 2, 3, 4, 5
 4root@Server-Debian-Jzh:~# echo ${arr[@]:1}
 52, 3, 4, 5
 6root@Server-Debian-Jzh:~# s=1;e=2
 7root@Server-Debian-Jzh:~# echo ${arr[@]:$s:$e}
 82, 3,
 9
10# 切片后不加括号的后果:
11root@Server-Debian-Jzh:~# tarr=${arr[@]:$s:$e}
12root@Server-Debian-Jzh:~# echo ${tarr[0]}
132, 3,

$@ 和 数组

$@ 不是真正的数组,如需使用上述取值和切片特性,需将其转换为数组:

1args=( $@ ) # convert to array

$@ 可以直接嵌入命令中而数组不可以:

1/bin/bash t.sh $val1 $@

关于 $@ 的数据结构,这是一段 chatgpt 的回答,挺不错的:

……

Q: but what i want to know is the data structure of $@

A: As I mentioned earlier, $@ is a special shell parameter in Bash that holds the positional parameters passed to the script or function. It is not technically an array in Bash, although it behaves like one in many ways.

Under the hood, $@ is actually a space-separated list of strings, with each string representing an individual positional parameter. When the shell expands $@, it splits this list into separate words, treating each space as a delimiter.

So you can think of the data structure of $@ as a simple list or sequence of strings, where each string represents an argument passed to the script or function. While it doesn’t have all the advanced functionality of a true array, such as indexed access and manipulation, it is still a very useful and versatile tool in Bash scripting.

算术运算

1[root@VM-0-11-centos ~]# a=1
2[root@VM-0-11-centos ~]# b=$((a*12))
3[root@VM-0-11-centos ~]# echo $b
412

比较运算

指令:-eq -ne -lt -gt -ge -le

注:字符串比较直接用 “==” 而不是上述指令。

1[root@VM-0-11-centos ~]# a=10
2[root@VM-0-11-centos ~]# [ $a -eq 10 ] && echo yes
3yes
4[root@VM-0-11-centos ~]# [ $a -ge 11 ] && echo yes || echo no
5no

指令:-a -o

1[root@VM-0-11-centos ~]# a=10;b=12;
2[root@VM-0-11-centos ~]# [ $a -lt 11 -a $b -lt 13 ] && echo yes || echo no
3yes
4[root@VM-0-11-centos ~]# [ $a -lt 11 -a $b -lt 11 ] && echo yes || echo no
5no

字符串运算

  1. -z(即 zero)检测字符串长度是否为 0,为 0 返回 true。
  2. str 检测字符串是否为空,不为空返回 true。
1[root@VM-0-11-centos ~]# [ -z "jzh" ] && echo yes || echo no
2no
3[root@VM-0-11-centos ~]# [ "jzh" == "zh" ] && echo yes || echo no
4no

字符串的引号使用

双引号与单引号效果不一样,如下:

1root@ubuntu2004:~# echo "$PATH"
2/usr/local/java/jdk1.8.0_311/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:...
3root@ubuntu2004:~# echo '$PATH'
4$PATH

获取时间

1# 输出格式化时间
2[root@VM-0-11-centos ~]# date '+%Y-%m-%d %H:%M:%S'
32022-04-10 13:22:04
4# 输出当前时间戳
5[root@VM-0-11-centos ~]# date +%s
61649568128

条件判断

注:中括号两端要有空白符。

1[root@VM-0-11-centos tmp]# [ "a" == "b" ] && echo hello || echo bye
2bye
3[root@VM-0-11-centos tmp]# [ "a" == "a" ] && echo hello || echo bye
4hello

文件运算

  1. -r 即 read
  2. -w 即 write
  3. -x 即 exec
  4. -s 即文件不为空
  5. -e 即 exist
1[root@VM-0-11-centos ~]# touch t.sh
2[root@VM-0-11-centos ~]# [ -s ./t.sh ] && echo yes || echo no
3no
4[root@VM-0-11-centos ~]# [ -e ./t.sh ] && echo yes || echo no
5yes

读取输入

read -p “prompt words” var_name

1[root@VM-0-11-centos ~]# read -p "age:" age
2age:12
3[root@VM-0-11-centos ~]# echo $age
412

read -a variable_name (读取数组)

1[root@VM-0-11-centos tmp]# read -a arr
21 2 3 4 5
3[root@VM-0-11-centos tmp]# echo ${arr[4]}
45

条件判断语句

if else

1if [  ] || [  ]; then
2	do_something
3elif [  ] && [  ]; then
4	do_something
5else
6	do_something
7fi

case

 1case ${var} in
 2"condition1")
 3do_something
 4;;
 5"condition2")
 6do_something
 7;;
 8*) #anything
 9do_something
10;;
11esac

循环语句

while

1while [ condition ]
2do
3	do_something
4done

when meet the condition, start the loop.

until

1until [ condition ]
2do
3	do_something
4done

when meet the condition, end the loop.

for

遍历数组:

1for $var in ${array}
2do
3	do_something
4done

遍历指定数字序列:

1for $var in {1..100}
2do
3	do_something
4done

条件遍历:

1for ( (i=1; i<=${var}; i++) )
2do
3	do_something
4done

sh 命令

  • -n 不执行,只检查语法 not execute but check
  • -v 执行前输出脚本内容 view the script
  • -x 将使用到脚本内容输出