shell脚本通常以#!/bin/bash
起始
脚本的执行方式有两种。
-
将脚本名作为命令行参数:
bash myScript.sh
-
授予脚本执行权限,将其变为可执行文件:
chmod 755 myScript.sh ./myScript.sh
终端中显示输出
$ echo "Welcome to Bash"
Welcome to Bash
双引号允许shell解释字符串中出现的特殊字符。单引号不会对其做任何解释
echo -e
接受双包含转义序列的双引号字符串作为参数
echo -e "1\t2\t3"
1 2 3
文本颜色是由对应的色彩码来描述的。其中包括:重置=0,黑色=30,红色=31,绿色=32, 黄色=33,蓝色=34,洋红=35,青色=36,白色=37
要打印彩色文本,可输入如下命令:
echo -e "\e[1;31m This is red text \e[0m"
彩色背景,经常使用的颜色码是:重置=0,黑色=40,红色=41,绿色=42,黄色=43, 蓝色=44,洋红=45,青色=46,白色=47
要设置彩色背景的话,可输入如下命令:
echo -e "\e[1;42m Green Background \e[0m"
变量与环境变量
var="value"
# 将"value"赋给变量var
echo $var
用env
或printenv
命令查看当前shell 中所定义的全部环境变量
在PATH中添加一条新路径,可以使用如下命令:
export PATH="$PATH:/home/user/bin"
另外还有一些众所周知的环境变量:HOME
、PWD
、USER
、UID
、SHELL
等
获得字符串的长度
$ var=12345678901234567890
$ echo ${#var}
20
识别当前所使用的shell echo $SHELL
、 echo $0
检查是否为超级用户
If [ $UID -ne 0 ]; then
echo Non root user. Please run as root.
else
echo Root user
fi
操作符[]
result=$[ no1 + no2 ]
在[]
中可以使用$
前缀
result=$[ $no1 + 5 ]
文件描述符与重定向
文件描述符是与某个打开的文件或数据流相关联的整数。文件描述符0、 1以及2是系统预留的
- 0 —— stdin (标准输入)
- 1 —— stdout(标准输出)
- 2 —— stderr(标准错误)
使用大于号将文本保存到文件中 $ echo "This is a sample text 1" > temp.txt
使用双大于号将文本追加到文件中 $ echo "This is sample text 2" >> temp.txt
使用2>(数字2以及大于号)将stderr重定向到out.txt $ ls + 2> out.txt
有一种方法既可以将数据重定向到文件,还可以提供一份重定向数据的副本作为管道中后续命令的stdin。tee
命令从stdin中读取,然后将输入数据重定向到stdout以及一个或多个文件中
command | tee FILE1 FILE2 | otherCommand
$ cat a* | tee out.txt | cat -n
重定向脚本内部的文本块
#!/bin/bash
cat<<EOF>log.txt
This is a generated file. Do not edit. Changes will be overwritten.
EOF
出现在cat <<EOF>log.txt
与下一个EOF行之间的所有文本行都会被当作stdin数据。 log.txt文件的内容显示如下:
$ cat log.txt
This is a generated file. Do not edit. Changes will be overwritten.
数组与关联数组
在单行中使用数值列表来定义一个数组
array_var=(test1 test2 test3 test4 test5 test6) #这些值将会存储在以0为起始索引的连续位置上
打印出特定索引的数组元素内容
echo ${array_var[0]}
test1
index=5
echo ${array_var[$index]}
test6
以列表形式打印出数组中的所有值
$ echo ${array_var[*]}
test1 test2 test3 test4 test5 test6
打印数组长度(即数组中元素的个数):
$ echo ${#array_var[*]}
6
关联数组中,我们可以用任意的文本作为数组索引。首先,需要使用声明语句将一个变量 定义为关联数组:
$ declare -A fruits_value
$ fruits_value=([apple]='100 dollars' [orange]='150 dollars')
显示数组内容:
$ echo "Apple costs ${fruits_value[apple]}"
Apple costs 100 dollars
列出数组索引
$ echo ${!fruits_value[*]}
orange apple
别名
创建别名
$ alias new_command='command sequence'
下面的命令为apt-get install
创建了一个别名:
$ alias install='sudo apt-get install'
alias命令的效果只是暂时的。一旦关闭当前终端,所有设置过的别名就失效了。为了 使别名在所有的shell中都可用,可以将其定义放入~/.bashrc
文件中
$ echo 'alias cmd="command seq"' >> ~/.bashrc
如果需要删除别名,只需将其对应的定义(如果有的话)从~/.bashrc
中删除,或者使用 unalias
命令。也可以使用alias example=
,这会取消别名example
采集终端信息
tput
命令的功能演示
获取终端的行数和列数:
tput cols
tput lines
打印出当前的终端名:
tput longname
将光标移动到坐标(100,100)处:
tput cup 100 100
设置终端背景色:
tput setb n
#其中,n可以在0到7之间取值。
设置终端前景色:
tput setf n
# 其中,n可以在0到7之间取值。
设置文本样式为粗体:
tput bold
设置下划线的起止:
tput smul tput rmul
删除从当前光标位置到行尾的所有内容:
tput ed
输入密码时,脚本不应该显示输入内容。在下面的例子中,我们将看到如何使用stty
来 实现这一需求
#!/bin/sh
#Filename: password.sh
echo -e "Enter password: "
# 在读取密码前禁止回显
stty -echo
read password
# 重新允许回显
stty echo
echo
echo Password read.
stty
命令的选项-echo
禁止将输出发送到终端,而选项echo
则允许发送输出。
调试脚本
使用选项-x
,启用shell脚本的跟踪调试功能:
$ bash -x script.sh
使用set -x
和set +x
对脚本进行部分调试
#!/bin/bash
#文件名: debug.sh
for i in {1..6};
do
set -x
echo $i
set +x
done
echo "Script executed"
在上面的脚本中,只会打印出echo $i
的调试信息,因为使用-x和+x对调试区域进行 了限制。
set -x
:在执行时显示参数和命令。
set +x
:禁止调试。
set -v
:当命令进行读取时显示输入。
set +v
:禁止打印输入。
把第一行从#!/bin/bash
改成 #!/bin/bash -xv
,这样一来,不用任何其他选项就可以 启用调试功能了
函数和参数
$0
是脚本名称。$1
是第一个参数。$2
是第二个参数。$n
是第n个参数。- “
$@
“被扩展成”$1” “$2” "$3"等。 - “
$*
“被扩展成”$1c$2c$3”,其中c是IFS的第一个字符。 - "
$@
“要比”$*
“用得多。由于”$*
"将所有的参数当作单个字符串,因此它很少被使用。
函数和别名乍一看很相似,不过两者在行为上还是略有不同。大的差异在于函数参数可以 在函数体中任意位置上使用,而别名只能将参数放在命令尾部。
如果想获得/sbin/ifconfig
文件中设备对应的IP地址,可以尝试这样做:
$> alias wontWork='/sbin/ifconfig | grep'
$> wontWork eth0
eth0 Link encap:Ethernet HWaddr 00:11::22::33::44:55
如果我们使用函数来实现的话,可以将 设备名作为参数传入ifconfig
,不再交给grep
:
$> function getIP() { /sbin/ifconfig $1 | grep 'inet '; }
$> getIP eth0
inet addr:192.168.1.2 Bcast:192.168.255.255 Mask:255.255.0.0
shift
命令可以将参数依次向左移动一个位 置,让脚本能够使用$1
来访问到每一个参数
$ cat showArgs.sh
for i in `seq 1 $#`
do
echo $i is $1
shift
done
$ sh showArgs.sh a b c
1 is a
2 is b
3 is c
读入 n个字符
从输入中读取n个字符并存入变量variable_name:
read -n number_of_chars variable_name
用无回显的方式读取密码:
read -s var
使用read显示提示信息:
read -p "Enter input:" var
在给定时限内读取输入:
read -t timeout var
例如:
$ read -t 2 var
#在2秒内将键入的字符串读入变量var
用特定的定界符作为输入行的结束:
read -d delim_char var
例如:
$ read -d ":" var
hello: #var被设置为hello
比较与测试
们可以用if、 if else以及逻辑运算符来测试
[ condition ] && action;
# 如果condition为真,则执行action
[ condition ] || action;
# 如果condition为假,则执行action
算术比较
[ $var
-eq 0 ] #当$var
等于0时,返回真
[ $var
-ne 0 ] #当$var
不为0时,返回真
● -gt:大于。
● -lt:小于。
● -ge:大于或等于。
● -le:小于或等于
-a是逻辑与操作符,-o是逻辑或操作符
文件系统相关测试
● [ -f $file_var ]:如果给定的变量包含正常的文件路径或文件名,则返回真。
● [ -x $var ]:如果给定的变量包含的文件可执行,则返回真。
● [ -d $var ]:如果给定的变量包含的是目录,则返回真。
● [ -e $var ]:如果给定的变量包含的文件存在,则返回真。
● [ -c $var ]:如果给定的变量包含的是一个字符设备文件的路径,则返回真。
● [ -b $var ]:如果给定的变量包含的是一个块设备文件的路径,则返回真。
● [ -w $var ]:如果给定的变量包含的文件可写,则返回真。
● [ -r $var ]:如果给定的变量包含的文件可读,则返回真。
● [ -L $var ]:如果给定的变量包含的是一个符号链接,则返回真。
字符串比较
● [[ -z $str1 ]]:如果str1为空串,则返回真。
● [[ -n $str1 ]]:如果str1不为空串,则返回真。