shell用法整理

使用 set 和 eval 取当前的运行级别

源码出自 CentOS6.X系统 sshd 服务脚本:/etc/init.d/sshd

1
2
3
4
[user1@study ~]$ runlevel=$(set -- $(runlevel); eval "echo \$$#" )
[user1@study ~]$ echo ${runlevel}
3
[user1@study ~]$

分析:

runlevel 命令执行结果通过 set -- 根据分隔符IFS,把值依次赋给位置参数 ($1,$2,$3…)

1
2
3
4
5
6
7
8
9
10
[user1@study ~]$ runlevel
N 3
[user1@study ~]$ set -- $(runlevel)
[user1@study ~]$ echo $1
N
[user1@study ~]$ echo $2
3
[user1@study ~]$ echo $1 $2
N 3
[user1@study ~]$

$#取得位置参数的个数为两个

1
2
3
[user1@study ~]$ echo $#
2
[user1@study ~]$

要取的数值为第二个参数即最后一个,使用 $2 即可取得第二个位置参数,这里的 2 使用 $# 来代替。由于 $$ 代表当前命令的PID,因此需要转义 $\$$#

要用 eval 做二次扫描,把 echo 的字符串当做命令解析,第二次解析 $2 的值为 3 。不进行解析的话 $2 只能当做纯字符串输出

1
2
3
4
5
6
7
8
9
10
[user1@study ~]$ echo $$# 
1343#
# 这里$$输出了进程pid,然后输出#

[user1@study ~]$ echo \$$#
$2
# 等同于 echo $2

[user1@study ~]$ eval "echo \$$#"
3

判断变量是否为整数

方法一:使用expr做计算,判断命令执行返回值

1
2
expr $1 + 1 &>/dev/null
[ $? -eq 0 ] && echo "int" || echo "not int"

方法二:使用变量字符串替换的结果做条件判断

1
2
3
4
num=2
[ -n ${num} -a "${num}" = "${num//[^0-9]/}" ] && echo "int" || echo "not int"
# 或
[ -n ${num} -a -z "${num//[0-9]/}" ] && echo "int" || echo "not int"

方法三:使用shell正则做条件判断

1
2
3
4
5
6
7
8
check_int(){
local char=$1
if [[ $char =~ ^[1-9][0-9]*$ ]];then
return 0
else
return 1
fi
}

匹配指定格式的文件名

源码出自CentOS6.X系统的命令脚本:/usr/bin/ssh-copy-id,用到了expr的表达式 expr STRING : REGEXP,还需要注意 expr 命令最好使用绝对路径

1
2
3
4
5
6
L_ID_FILE="~/.ssh/test.pub" 
if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then
PUB_ID_FILE="$L_ID_FILE"
else
PUB_ID_FILE="$L_ID_FILE.pub"
fi

字串 STRING 中一旦被正则表达式 REGEXP 匹配到,就返回匹配到的字符串的长度,否则返回 0

1
2
3
4
5
6
[user1@study ~]$ a=test.txt
[user1@study ~]$ expr $a : ".*\.txt$"
8
[user1@study ~]$ expr $a : ".*\.txta$"
0
[user1@study ~]$

判断字符串是否不为空

test "string" 等同于 [ "string" ] 等同于 [ -n "string" ]

1
2
3
4
5
6
7
8
9
10
11
[user1@study ~]$ test "fdsa" && echo not null || echo 0
not null
[user1@study ~]$ test "" && echo not null || echo 0
0
[user1@study ~]$ test " " && echo not null || echo 0
not null
[user1@study ~]$ [ -n "" ] && echo not null || echo 0
0
[user1@study ~]$ [ -n " " ] && echo not null || echo 0
not null
[user1@study ~]$

使用rename实现批量改文件名

将后缀名 .conf 的文件批量改为 .conf.bak

1
2
3
4
5
6
7
8
9
10
[user1@study ~]$ ls *.conf
named10.conf named12.conf named14.conf named16.conf named2.conf named4.conf named6.conf named8.conf
named11.conf named13.conf named15.conf named1.conf named3.conf named5.conf named7.conf named9.conf
[user1@study ~]$ rename .conf{,.bak} *.conf
[user1@study ~]$ ls *.conf
ls: cannot access *.conf: No such file or directory
[user1@study ~]$ ls *.conf.bak
named10.conf.bak named12.conf.bak named14.conf.bak named16.conf.bak named2.conf.bak named4.conf.bak named6.conf.bak named8.conf.bak
named11.conf.bak named13.conf.bak named15.conf.bak named1.conf.bak named3.conf.bak named5.conf.bak named7.conf.bak named9.conf.bak
[user1@study ~]$

将后缀名 .conf.bak 的文件改为 .conf

1
2
3
4
5
6
7
8
9
10
[user1@study ~]$ ls *.conf.bak
named10.conf.bak named12.conf.bak named14.conf.bak named16.conf.bak named2.conf.bak named4.conf.bak named6.conf.bak named8.conf.bak
named11.conf.bak named13.conf.bak named15.conf.bak named1.conf.bak named3.conf.bak named5.conf.bak named7.conf.bak named9.conf.bak
[user1@study ~]$ rename .conf.bak .conf *.conf.bak
[user1@study ~]$ ls *.conf.bak
ls: cannot access *.conf.bak: No such file or directory
[user1@study ~]$ ls *.conf
named10.conf named12.conf named14.conf named16.conf named2.conf named4.conf named6.conf named8.conf
named11.conf named13.conf named15.conf named1.conf named3.conf named5.conf named7.conf named9.conf
[user1@study ~]$

使用内置命令type取命令的路径

1
2
3
4
5
[user1@study ~]$ type -path ssh
/bin/ssh
[user1@study ~]$ which ssh
/bin/ssh
[user1@study ~]$

检查域名是否被干扰

向根请求解析指定的域名,正常情况下根不会返回任何A记录,只会返回它所属下一级域的NS记录。如果 dig +short 返回的值为空则说明域名未被干扰,如果返回一个A记录的IP地址,说明域名在请求解析的途中被拦截或干扰。

1
2
3
4
5
6
7
[user1@study ~]$ source_ip=192.168.127.123
[user1@study ~]$ query_answer=$(dig +short -b ${source_ip} @a.root-servers.net. www.baidu.com >/dev/null 2>&1)
[user1@study ~]$ echo ${query_answer}

[user1@study ~]$ test -z "${query_answer}" && echo ok || echo not ok
ok
[user1@study ~]$
有钱任性,请我吃包辣条
0%