Unix Shell Programming - tenji/ks GitHub Wiki
必须在调用函数地方之前,声明函数,shell 脚本是逐行运行。不会像其它语言一样先预编译。一次必须在使用函数前先声明函数。
在非交互式模式下alias
扩展功能默认是关闭的,此时虽然可以定义alias
别名,但是 shell 不会将alias
别名扩展成对应的命令,而是将alias
别名本身当作命令执行,如果 shell 内置命令和 PATH 中均没有与alias
别名同名的命令,则 shell 会找不到指定的命令。
命令执行状态只有0
为真,其它均为假,也就是说可以命令执行结果是否为0
来判断命令是否执行成功。比如:
#!/bin/bash -l
grep "test" /home/admin/web.xml > /dev/null
if [ $? -eq 0 ]; then
echo "Found!"
以上脚本可以判断文件web.xml
中是否包含字符串test
,但是需要注意的是,如果脚本中设置了set -e
,命令执行状态不为真,也就是不为0
的时候,会导致脚本出错自动退出。
shell 中使用管道会生成一个子 shell,在子 shell 中使用 while, for 循环的代码也是在子 shell 中执行的,所以在循环中的修改的变量只在子 shell 中有效,当循环结束时,会回到主 shell,子 shell 中修改的变量不会影响主 shell 中的变量。
A="1"
B="2"
C="/home/linux/a"
cat $C | grep -v '^commit' | while read line
do
if [ "x$A" = "x1" ]; then
B=$A
echo $B
fi
done
echo $B
# 第一个echo打印的是1
# 第二个echo打印的是2
这里是因为在子 shell 中的 while 循环中的 B 只是主 shell 中 B 的一个副本,在子 shell 中对 B 重新赋值是不能影响到父 shell 的,所以最后 echo $B 时值没有改变。但是以下是可以重新赋值的,因为这里没有管道,也就不存在子 shell 了。
while read line
do
if
B=$A
fi
done < $C
-
-n
读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
-
-v
一边执行脚本,一边将执行过的脚本命令打印到标准错误输出。
-
-x
提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。
-
grep (Global Regular Expression Print)
grep 命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来,擅长行处理和查找。
-
awk (Aho Weinberger Kernaighan)
AWK 是一种处理文本文件的语言,它将文件作为记录序列处理,每行内容都会被分割成一系列的域,因此,我们可以认为一行的第一个词为第一个域,第二个词为第二个,以此类推,擅长列处理。
-
sed (stream editor)
sed是一种流编辑器,它一次处理一行内容,擅长行处理和替换。
名称 | 说明 |
---|---|
$0 | 脚本名称 |
$1-9 | 脚本执行时的参数1到参数9 |
$? | 脚本的返回值 |
$# | 脚本执行时,输入的参数的个数 |
$@ | 输入的参数的具体内容 |
$* | 输入的参数的具体内容 |
$@
与$*
的区别:
-
$@
将输入的参数作为一个列表对象 -
$*
将输入的参数作为一个单词
- 判断命令是否存在
#!/bin/bash
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
- 判断命令是否执行成功
#!/bin/bash
if [ $? -eq 0 ]; then
命令正确的分支
else
命令失败的分支
fi
- 使用
getopts
来读取参数
#!/bin/bash
while getopts "a:bc" arg #选项后面的冒号表示该选项需要参数
do
case $arg in
a)
echo "a's arg:$OPTARG" #参数存在$OPTARG中
;;
b)
echo "b"
;;
c)
echo "c"
;;
?) #当有不认识的选项的时候arg为?
echo "unkonw argument"
exit 1
;;
esac
done
可以结合一下语句来判断参数:
if [ ! -n "$1" ] ;then
echo "Usage: install.sh -p [LOGSTASH_PATH]"
exit 1
fi
- 脚本出错自动退出运行
#!/bin/bash
set -e
- 读取JSON格式数据(日志文件等)中的某个字段
#!/bin/bash
grep -Po 'receive_time[" :]+\K[^,"]+' android_log.json |awk '$1>=1558944000000 && $1 <=1558947600000' |wc -l
- 判断字符是否符合指定正则表达式
#!/bin/bash
if ! [[ $target_release_version =~ ^[0-9]{1}\.[0-9]{1}\.[0-9]{1}$ ]]; then
echo 'Unavailable release version, use version like 2.0.0' >&2
exit 1
fi
- 读取XML文件的属性值
比如读取一下的
version
值:
<version>0.0.1-SNAPSHOT</version>
#!/bin/bash
version=`awk '/<version>/,/<version>/ {print $0}' pom.xml | awk -v FS="<version>" -v OFS=" " '{print $2}' | awk -v FS="</version>" -v OFS=" " '{print $1}' | head -n 1`
echo "The version is: $version"
- 读取文件名
#!/bin/bash
filename=`ls -l | awk '{print $9}'`
echo $filename
- 逐行读取文件
#!/bin/bash
cat partitions.log | while read line
do
echo $line
done