Shell笔记一
内容来自:
需要知道是,参考在 Mac 上将 zsh 用作默认 Shell:
从 macOS Catalina 版开始,您的 Mac 将使用 zsh 作为默认登录 Shell 和交互式 Shell。您还可以在较低版本的 macOS 中将 zsh 设置为默认 Shell。
使用$ cat /etc/shells
命令来查看系统的可用Shell,在Mac OS系统下,输出结果如下:
# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.
/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
查看默认的shell,使用$ echo $SHELL
,输出 SHELL
环境变量
第一个shell脚本
#!/bin/bash
echo "Hello World !"
#!
是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shellecho
命令用于向窗口输出文本
直接运行是会报错误的,因为没有权限执行(Permission denied),需要给权限。下面方式
chmod +x ./demo1 # 使每个人都有执行的权限
chmod +rx ./demo1 # 使每个人都有读和执行的权限
chmod u+rx ./demo1 # 仅仅使脚本文件拥有者有读和执行的权限
chmod u+x ./demo1 # 只有自己可以执行,其它人不能执行
chmod ug+x ./demo1 # 只有自己以及同一群可以执行,其它人不能执行
chmod 555 ./demo1 # 使每个人都有读和执行的权限
chmod 777 ./demo1
chmod
命令可参考:
使用./hello.sh
来执行脚本
再如下面的例子,使用 read
命令从 stdin
获取输入并赋值给 PERSON
变量,最后在 stdout
上输出
#!/bin/bash
echo "What is your name?"
read PERSON
echo "Hello, $PERSON"
变量
脚本语言在定义变量时不需要指定类型
在 Bash shell
中,每一个变量的值都是字符串,无论你给变量赋值时有没有使用引号,值都会以字符串的形式存储。
定义变量的方式:
variable=value
variable='value'
variable="value"
如:
#!/bin/bash
url=http://www.baidu.com
echo $url
name='laowang'
echo $name
author="老王"
echo $author
注意赋值号的周围不能有空格,如:
#!/bin/bash
url = http://www.baidu.com
会提示错误:
使用变量
使用一个定义过的变量,只要在变量名前面加美元符号$
即可
变量名外面的花括号{ }
是可选的,加不加都行,用来识别变量的边界
#!/bin/bash
skill="Java"
echo "I am good at ${skill}Script"
输出结果为I am good at JavaScript
单引号和双引号的区别
url="www.baidu.com"
website1='百度:${url}'
website2="百度:${url}"
echo $website1
echo $website2
输出结果为:
百度:${url}
百度:www.baidu.com
区别:
- 以单引号
' '
包围变量的值时,单引号里面是什么就输出什么 - 以双引号
" "
包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出
将命令的结果赋值给变量
两种方式:
variable=`command`
variable=$(command)
- 用
反引号
包围起来 - 把命令用
$()
包围起来
如下的例子,获取log.txt
文件的内容,赋值给log
#!/bin/bash
log=$(cat log.txt)
echo ${log}
cat
的含义参考:
只读变量
readonly
将变量定位为只读变量
删除变量
使用 unset
命令可以删除变量。语法:
unset variable_name
特殊变量
参考:
变量 | 含义 |
---|---|
$0 | 当前脚本的文件名 |
$n | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
$# | 传递给脚本或函数的参数个数。 |
$* | 传递给脚本或函数的所有参数。 |
$@ | 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同 |
$? | 上个命令的退出状态,或函数的返回值。 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
如下的例子:
#!/bin/bash
echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters : $#"
如果运行./hello.sh arg1 arg2
,输出结果为:
File Name: ./hello.sh
First Parameter : arg1
First Parameter : arg2
Quoted Values: arg1 arg2
Quoted Values: arg1 arg2
Total Number of Parameters : 2
$*
和 $@
的区别
$*
和$@
都表示传递给函数或脚本的所有参数,不被双引号(" ")
包含时,都以"$1"
"$2"
…"$n"
的形式输出所有参数。
但是当它们被双引号(" ")
包含时,"$*"
会将所有的参数作为一个整体,以"$1 $2 … $n"
的形式输出所有参数;"$@"
会将各个参数分开,以"$1"
"$2"
…"$n"
的形式输出所有参数。
下面的例子可以清楚的看到 $*
和 $@
的区别:
#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\$@=" $@
echo "\"\$@\"=" "$@"
echo "print each param from \$*"
for var in $*
do
echo "$var"
done
echo "print each param from \$@"
for var in $@
do
echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
echo "$var"
done
执行 ./test.sh "a" "b" "c" "d"
,看到下面的结果:
$*= a b c d
"$*"= a b c d
$@= a b c d
"$@"= a b c d
print each param from $*
a
b
c
d
print each param from $@
a
b
c
d
print each param from "$*"
a b c d
print each param from "$@"
a
b
c
d
退出状态
$?
可以获取上一个命令的退出状态。所谓退出状态,就是上一个命令执行后的返回结果。
退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0
,失败返回 1
。
替换
参考:
转义字符
echo -e
与echo
的区别,如下:
-e
表示对转义字符进行替换。如果不使用 -e
选项,将会原样输出
a=10
echo -e "Value of a is $a \n"
输出为:
#!/bin/bash
a=10
echo "Value of a is $a \n"
命令替换
命令替换是指Shell可以先执行命令,将输出结果暂时保存,在适当的地方输出。
`command`
如下的命令:
#!/bin/bash
DATE=`date`
echo "Date is $DATE"
USERS=`who | wc -l`
echo "Logged in user are $USERS"
UP=`date ; uptime`
echo "Uptime is $UP"
输出结果为:
变量替换
变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值
可以使用的变量替换形式:
形式 | 说明 |
---|---|
${var} | 变量本来的值 |
${var:-word} | 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。 |
${var:=word} | 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。 |
${var:?message} | 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以正常赋值。若此替换出现在Shell脚本中,那么脚本将停止运行。 |
${var:+word} | 如果变量 var 被定义,那么返回 word,但不改变 var 的值。 |
请看下面的例子:
#!/bin/bash
echo ${var:-"Variable is not set"}
echo "1 - Value of var is ${var}"
echo ${var:="Variable is not set"}
echo "2 - Value of var is ${var}"
unset var
echo ${var:+"This is default value"}
echo "3 - Value of var is $var"
var="Prefix"
echo ${var:+"This is default value"}
echo "4 - Value of var is $var"
echo ${var:?"Print this message"}
echo "5 - Value of var is ${var}"
运行结果:
Variable is not set
1 - Value of var is
Variable is not set
2 - Value of var is Variable is not set
3 - Value of var is
This is default value
4 - Value of var is Prefix
Prefix
5 - Value of var is Prefix
运算符
参考:
原生bash
不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk
和 expr
,expr
最常用
expr
是一款表达式计算工具,使用它能完成表达式的求值操作。
#!/bin/bash
val=`expr 2 + 2`
echo "Total value : $val"
输出结果为:
Total value : 4
注意:
1.表达式和运算符之间要有空格,如果写成
val=`expr 2+2`
输出时会变成如下的结果:
Total value : 2+2
2.完整的表达式要被 ` `
包含,注意这个字符不是常用的单引号
算数运算符
a=10
b=20
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | `expr $a + $b` 结果为 30 |
- | 减法 | `expr $a - $b` 结果为 10 |
* | 乘法 | `expr $a \* $b` 结果为 200 |
/ | 除法 | `expr $b / $a` 结果为 2 |
% | 取余 | `expr $b % $a` 结果为 0 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a |
== | 相等。用于比较两个数字,相同则返回 true | [ $a == $b ] 返回 false |
!= | 不相等。用于比较两个数字,不相同则返回 true | [ $a != $b ] 返回 true |
关系运算符
a=10
b=20
运算符 | 说明 | 举例 |
---|---|---|
-eq | 检测两个数是否相等,相等返回 true | [ $a -eq $b ] 返回 false |
-ne | 检测两个数是否相等,不相等返回 true | [ $a -ne $b ] 返回 true |
-gt | 检测左边的数是否大于右边的,如果是,则返回 true | [ $a -gt $b ] 返回 false |
-lt | 检测左边的数是否小于右边的,如果是,则返回 true | [ $a -lt $b ] 返回 true |
-ge | 检测左边的数是否大等于右边的,如果是,则返回 true | [ $a -ge $b ] 返回 false |
-le | 检测左边的数是否小于等于右边的,如果是,则返回 true | [ $a -le $b ] 返回 true |
布尔运算符
a=10
b=20
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算,表达式为 true 则返回 false,否则返回 true | [ ! false ] 返回 true。 |
-o | 或运算,有一个表达式为 true 则返回 true | [ $a -lt 20 -o $b -gt 100 ] 返回 true |
-a | 与运算,两个表达式都为 true 才返回 true | [ $a -lt 20 -a $b -gt 100 ] 返回 false |
字符串运算符
a="abc"
b="efg"
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等,相等返回 true | [ $a = $b ] 返回 false |
!= | 检测两个字符串是否相等,不相等返回 true | [ $a != $b ] 返回 true |
-z | 检测字符串长度是否为0,为0返回 true | [ -z $a ] 返回 false |
-n | 检测字符串长度是否为0,不为0返回 true | [ -n $a ] 返回 true |
str | 检测字符串是否为空,不为空返回 true | [ $a ] 返回 true |
文件测试运算符
#变量 file 表示文件“/var/www/tutorialspoint/unix/test.sh”,它的大小为100字节,具有 rwx 权限
file="/var/www/tutorialspoint/unix/test.sh"
操作符 | 说明 | 举例 |
---|---|---|
-r file | 检测文件是否可读,如果是,则返回 true | [ -r $file ] 返回 true |
-w file | 检测文件是否可写,如果是,则返回 true | [ -w $file ] 返回 true |
-x file | 检测文件是否可执行,如果是,则返回 true | [ -x $file ] 返回 true |
字符串
字符串拼接
#!/bin/bash
my_name="laowang"
greeting="hello, "$my_name" !"
greeting_1="hello, ${my_name} !"
echo ${greeting}
echo ${greeting_1}
输出结果为:
hello, laowang !
hello, laowang !
获取字符串长度
#!/bin/bash
string="abcde"
echo "length is ${#string}"
输出结果为:
length is 5
提取子字符串
参考:
从字符串左边开始计数,格式为:
${string: start :length}