记录整理一下目前遇到的shell相关的用法, 还不错,加深一些印象。
Shell $0 $? $! 变量解析
参数 | 含义 |
---|---|
$$ | Shell本身的PID(ProcessID) |
$! | Shell最后运行的后台Process的PID |
$? | 最后运行的命令的结束代码(返回值) |
$- | 使用Set命令设定的Flag一览 |
$* | 所有参数列表。如"$*"用「"」括起来的情况、以"?$1 ?$2 … $n"的形式输出所有参数 |
$@ | 所有参数列表。如"$@"用「"」括起来的情况、以"?$1" "?$2" … "$n" 的形式输出所有参数 |
$# | 添加到Shell的参数个数 |
$0 | Shell本身的文件名 |
$1~$n | 添加到Shell的各参数值。$1是第1参数、$2是第2参数… |
$* 取当前shell的所有参数,将所有的命令行视为单个字符串,相当于"$1?$2"
$@ 取当前shell的所有参数保留参数里的空白,,相当于$1,$2,一般用其进行参数传递
#!/bin/sh
echo "Args Count:$#"
echo "Process ID:$$"
echo "Arg 0:$0"
echo "Arg 1:$1"
echo "Arg 2:$2"
echo "Args List:$@"
echo "Args List2:$*"
for i in "$*";do
echo $i
done
echo "******"
for i in "$@";do
echo $i
done
"""
Args Count:3
Process ID:84735
Arg 0:./echo.sh
Arg 1:hello
Arg 2:pretty
Args List:hello pretty world
Args List2:hello pretty world
hello pretty world
******
hello
pretty
world
"""
Shell中冒号的作用
: 就是什么也不做(do nothing)即空命令,一般用在 if...then... 条件中,用作什么也不做的命令,类似python 的PASS or continue之类的jump动作。
if [ -f "$0" ]; then
:
else
echo ‘the file do not exit !‘
fi
Shell中多行注解反注解:
方法一:#,使用vim 进行多行注解,vim支持块处理
1.Ctrl+v进入visual block模式, 调整上下选中注解行(j 或者k也可以上下移动)
2.按shift+i(或者大写I),输入注释符(#或//),按一下或者两下Esc
3.反注解同理,control+V进入VISUAL BLOCK模式,按j或k选中多行,按l选中多列,按x或者d删除注释。
方法二:
冒号在Bash里也是一个命令,表示啥都不做,<<是输入重定向,两个EOF(可用其它特殊成对字符替代)之间的内容通过<<追加给冒号(:),但是冒号对它们啥都不做,就相当于没做任何处理和输出,就相当于注释了。
:<<EOF
echo "--1-- "
echo "--2--"
EOF
echo "Done"
AWK 中NR NF $NF的含义
NR表示已经读取域的记录数目,直观的含义是第几行
NF表示浏览记录的域的个数
awk ‘{print $1}’打印第一列
awk ‘{print $2}’打印第二列
NF表的是列数
如:a b c d
那么NF=4
$NF****就是表示第五列的值,就是一行数据最后一列的那个值
echo "a b c d" |awk ‘{print NF}‘
4
echo "a b c d" |awk ‘{print $0}‘
a b c d
echo "a b c d" |awk ‘{print $1}‘
a
echo "a b c d" |awk ‘{print $2}‘
b
echo "a b c d" |awk ‘{print $3}‘
c
echo "a b c d" |awk ‘{print $4}‘
d
echo "a b c d" |awk ‘{print $NF}‘
d
打印每行的行号,每行的列数(以空格区分列),对应的完整行内容
cat ~/Desktop/echo.sh |awk ‘{print NR,NF,$0}‘
1 1 #!/bin/sh
2 3 echo "Args Count:$#"
3 3 echo "Process ID:$$"
4 3 echo "Arg 0:$0"
5 3 echo "Arg 1:$1"
6 2 sleep 3
7 3 echo "Arg 2:$2"
8 3 echo "Args List:$@"
9 3 echo "Args List2:$*"
10 3 echo "Args ?。?:$-"
11 0
12 0
13 1 :<<EOF
14 3 echo "--1-- "
15 2 echo "--2--"
16 1 EOF
17 2 echo "Done1"
18 0
19 6 if [ -f "$0" ]; then
20 1 :
21 1 else
22 7 echo ‘the file do not exit !‘
23 1 fi
获取输出内容or文件多少行
1. df -h |awk ‘{print NR}‘ |tail -n1 #df -h 输出磁盘信息
2. awk ‘{print NR}‘ ~/Desktop/echo.sh|tail -n1
3. awk ‘END{print NR}‘ ~/Desktop/echo.sh
4. sed -n ‘$=‘ ~/Desktop/echo.sh or df -h |sed -n ‘$=‘
5. cat ~/Desktop/echo.sh |wc -l
打印指定第几行第几列
df -h |awk ‘NR==5{print $5}‘ #第五行第五列
shell if条件判断参数
Tips:
&&:用来执行条件成立后执行的命令
||:用来执行条件不成立后的执行命令
常规的变量引入,只需要$var即可,但如果有单引号扩起来的字符串,想引入变量,那么引入单引号即可取值
a=1;echo $a;echo ‘‘$a‘‘
判断变数是否为数字
if [ -z "$(echo $var | sed ‘s#[0-9]##g‘)" ];then
echo "Is Number"
else
echo "Not a Number:${var}"
fi
格式1: test 条件表达式
格式2: [ 条件表达式 ]
格式3: [[ 条件表达式 ]] 支持正则 =~
注意:
[ ] 和 [[ ]] 两边必须有空格
- 1.判断文件类型
判断参数 | 含义 |
---|---|
-e | 判断文件是否存在(任何类型文件) |
-f | 判断文件是否存在并且是一个普通文件 |
-d | 判断文件是否存在并且是一个目录 |
-L | 判断文件是否存在并且是一个软连接文件 |
-b | 判断文件是否存在并且是一个块设备文件 |
-S | 判断文件是否存在并且是一个套接字文件 |
-c | 判断文件是否存在并且是一个字符设备文件 |
-p | 判断文件是否存在并且是一个命名管道文件 |
-s | 判断文件是否存在并且是一个非空文件(有内容) |
cd ~/Desktop
Desktop % [ -s echo.sh ] && echo ‘非空‘ || echo "空"
非空
Desktop % [ -s echo1.sh ] && echo ‘非空‘ || echo "空"
空
Desktop % [ -f echo1.sh ] && echo ‘文件存在‘ || echo "不存在"
不存在
Desktop % [ -f echo.sh ] && echo ‘文件存在‘ || echo "不存在"
文件存在
- 2.判断文件权限
判断参数 | 含义 |
---|---|
-r | 当前用户对其是否可读 |
-w | 当前用户对其是否可写 |
-x | 当前用户对其是否可执行 |
-u | 是否有suid,高级权限冒险位 |
-g | 是否sgid,高级权限强制位 |
-k | 是否有t位,高级权限粘滞位 |
- 3.判断文件新旧
判断参数 | 含义 |
---|---|
file1 -nt file2 | 比较file1是否比file2新 |
file1 -ot file2 | 比较file1是否比file2旧 |
file1 -ef file2 | 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode |
Desktop % ln echo.sh echo_1.sh
Desktop % [ echo.sh -ef echo_1.sh ] && echo yes || echo no
yes
Desktop % [ echo.sh -ef echo_2.sh ] && echo yes || echo no
no
Desktop % [ echo.sh -ef echo2.sh ] && echo yes || echo no
yes
- 4.判断整数
判断参数 | 含义 |
---|---|
-eq | 相等 |
-ne | 不等 |
-gt | 大于 |
-lt | 小于 |
-ge | 大于等于 |
-le | 小于等于 |
#!/bin/bash
# 磁盘空间警报脚本
count=$(df -h |sed -n ‘$=‘)
for ((i=2; i<=$count; i++))
do
disk_name=`df -h |awk ‘NR==‘$i‘{print $1}‘`
disk_use=$(df -h |awk ‘NR==‘$i‘{print $5}‘|awk -F"%" ‘{print $1}‘)
if [ -z "$(echo $disk_use | sed ‘s#[0-9]##g‘)" ];then
if [ $disk_use -gt 90 ];then
echo "`date +%F-%H` disk warning...\t${disk_name} use:${disk_use}% "
fi
fi
done
- 5.判断字符串
判断参数 | 含义 |
---|---|
-z | 判断是否为空字符串,字符串长度为0则成立 |
-n | 判断是否为非空字符串,字符串长度不为0则成立 |
string1 = string2 | 判断字符串是否相等 |
string1 != string2 | 判断字符串是否不等 |
- 6.多重条件判断
判断符号 | 含义 | 举例 |
---|---|---|
-a 和 && | 逻辑与 | [ 1 -eq 1 -a 1 -ne 0 ] 或[ 1 -eq 1 ] && [ 1 -ne 0 ] |
-o 和 ||
|
逻辑或 | [ 1 -eq 1 -o 1 -ne 1 ] 或[ 1 -eq 1 ] || [1 -ne 1] |
&& 前面的表达式为真,才会执行后面的代码
|| 前面的表达式为假,才会执行后面的代码
; 只用于分割命令或表达式
数值比较
[ $(id -u) -eq 0 ] && echo "the user is root" || echo "the user is not root"
补充
test 、[ ] 和[[ ]]的区别
test命令通常做判断, test 命令和 [ ] 等同
可用于判断某个条件是否为真。可用于 字符串,数值和文件的测试。
[ "$A" = "$B" ] ##是否相等
[ "$A" != "$B" ] ##是否不相等
[ "$A" -eq "$B" ] ##是否相等
[ "$A" -ne "$B" ] ##是否不相等
[ "$A" -le "$B" ] ##是否小于等于
[ "$A" -lt "$B" ] ##是否小于
[ "$A" -ge "$B " ] ##是否大于等于
[ "$A" -gt "$B" ] ##是否大于
[ "$A" -ne "$B" -a "$A" -gt "$B" ] ##A 不等于 B 并且 A 大于B
[ "$A" -ne "$B" -o "$A" -gt "$B" ] ##A不等于B 或者 A大于B
[ -z "$A" ] ##是否为空
[ -n "$A" ] ##是否不为空
a=1;b=1
test "$a" = "$b" && echo yes || echo no
yes
[ "$a" = "$b" ] && echo yes || echo no
yes
test "$a" != "$b" && echo yes || echo no
no
[ "$a" != "$b" ] && echo yes || echo no
no
参考[shell中(),[]和[[]]的区别](https://developer.aliyun.com/article/318988)
-
首先,尽管很相似,但是从概念上讲,二者是不同层次的东西。
"[[",是关键字,许多shell(如ash bsh)并不支持这种方式。ksh, bash(据说从2.02起引入对[[的支持)等支持。
"["是一条命令, 与test等价,大多数shell都支持。在现代的大多数sh实现中,"["与"test"是内部(builtin)命令,换句话说执行"test"/"["时不会调用/some/path/to/test这样的外部命令(如果有这样的命令的话)。 -
[[]]结构比Bash版本的[]更通用。在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换。
用[[ ... ]]测试结构比用[ ... ]更能防止脚本里的许多逻辑错误。比如说,&&,||,<和>操作符能在一个[[]]测试里通过,但在[]结构会发生错误。
-
(( ))结构扩展并计算一个算术表达式的值。如果表达式值为0,会返回1或假作为退出状态码。一个非零值的表达式返回一个0或真作为退出状态码。这个结构和先前test命令及[]结构的讨论刚好相反。
-
[ ... ]为shell命令,所以在其中的表达式应是它的命令行参数,所以串比较操作符">" 与"<"必须转义,否则就变成IO改向操作符了(请参看上面2中的例子)。在[[中"<"与">"不需转义;
由于"[["是关键字,不会做命令行扩展,因而相对的语法就稍严格些。例如
在[ ... ]中可以用引号括起操作符,因为在做命令行扩展时会去掉这些引号,而在[[ ... ]]则不允许这样做。 -
[[ ... ]]可以进行算术扩展,支持正则表达式
正则判断
检查变数是否包含三位数字
var="123d"
re="^[0-9]{3,}"
if [[ $var =~ $re ]]; then
echo "true"
else
echo "not true"
fi