```
shell中的比较运算符:
-eq //等于
-ne //不等于
-gt //大于 (greater)
-lt //小于 (less)
-ge //大于等于
-le //小于等于
1. shell中如果是等于、不等于,既可以用 -eq、-ne (外面需要加中括号),也可以用 == 、!=(外面加中括号或双括号都行)
2. shell中如果是大于,大于等于,小于,小于等于,用 -gt, -ge,-lt,-le 的话,则需要加中括号。
3. shell中大于、大于等于,小于,小于等于想用 >,>=,<,<=,则需要加双括号,而不是中括号
整数比较
-gt, -lt,-ge,-le, -eq, -ne, 仅适用于整数,且比较运算符左右两边必须有空格,否则会被整体视为一个字符串(非空字符串,恒为正)
使用 > ,< ,>= , <= , != ,== 时,运算符左右两边可以使用空格,也可以不使用空格
浮点数比较
仅能使用使用 > ,< ,>= , <= , != ,== ,运算符左右两边不可以使用空格,不可使用字符型的比较运算符
常用形式:
用于单中括号[ ]中, 变量需要使用使用'$'符号,含 > 和 < 的符号时,需要使用'\'进行转义
if [ $a \> $b ]
用于双中括号[[ ]]中,变量需要使用使用'$'符号,比较运算符符号不需要转义(推荐使用)
if [[ $a > $b]]
用于双小括号(( ))中,变量可以不使用'$'符号,不需要使用转义,在代数比较时,只能用于整数比较(与C语言for循环中的判断条件语法相同)
if ((a > b))
Linux SHELL if 命令参数说明
–b 当file存在并且是块文件时返回真
-c 当file存在并且是字符文件时返回真
-d 当pathname存在并且是一个目录时返回真
-e 当pathname指定的文件或目录存在时返回真
-f 当file存在并且是正规文件时返回真
-g 当由pathname指定的文件或目录存在并且设置了SGID位时返回为真
-h 当file存在并且是符号链接文件时返回真,该选项在一些老系统上无效
-k 当由pathname指定的文件或目录存在并且设置了“粘滞”位时返回真
-p 当file存在并且是命令管道时返回为真
-r 当由pathname指定的文件或目录存在并且可读时返回为真
-s 当file存在文件大小大于0时返回真
-u 当由pathname指定的文件或目录存在并且设置了SUID位时返回真
-w 当由pathname指定的文件或目录存在并且可执行时返回真。一个目录为了它的内容被访问必然是可执行的。
-o 当由pathname指定的文件或目录存在并且被子当前进程的有效用户ID所指定的用户拥有时返回真。
Shell 里面比较字符写法:
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-le 小于等于
-ge 大于等于
-z 空串
= 两个字符相等
!= 两个字符不等
-n 非空串
```
```
if [[ "$1" == "wan" ]];then
$IPT4 -F mwan3_policy_balanced
$IPT4 -I mwan3_policy_balanced -m mark --mark 0x0/0x3f00 -j MARK --set-mark 0x100/0x3f00
else
$IPT4 -F mwan3_policy_balanced
$IPT4 -I mwan3_policy_balanced -m mark --mark 0x0/0x3f00 -j MARK --set-mark 0x200/0x3f00
fi
```
shell判断一个变量是否为NULL:
1.最直接简单的判断
[ ! $a ] && echo "a is null"
不用那些if语句了,直接缩短代码量。
2. 变量通过" "引号引起来
如下所示:,可以得到结果为 IS NULL.
#!/bin/sh a= if [ ! -n "$a" ]; then echo "IS NULL" else echo "NOT NULL" fi
3. 直接通过变量判断
如下所示:得到的结果为: IS NULL,跟第一种方法一样的,只是代码长一点,推荐使用第一种判断方式,简单明了。
#!/bin/sh a= if [ ! $a ]; then echo "IS NULL" else echo "NOT NULL" fi
4. 使用test判断
得到的结果就是: a is not set!
#!/bin/sh a= if test -z "$a" then echo "a is not set!" else echo "a is set !" fi
5. 使用""判断
#!/bin/sh a= if [ "$a" = "" ]; then echo "a is not set!" else echo "a is set !" fi
这种情况下容易让脚本报错
linux shell "2>&1"的含义:
=====================================================================
我们经常在代码中看到这样的语句:
1>/dev/null 2>&1 &
这段代码的意思是:将标准输出和标准错误输出都重定向到/dev/ null中。
/dev/null :我们可以将它理解为一个黑洞,所有写入它的内容都会丢失,并且尝试从它读却什么也读不到。
大家肯定会有这些疑问:
1)2>&1是什么意思,不能写成2>1吗?
2>&1:代表把标准错误输出重定向到标准输出中去,如果改成2>1的意思就是,试过的人知道,这是把标准错误输出重定向到名为“1”的文件中去了,所以我们在前面加&。
2)2>&1为什么要放后面
例子1:我们看下面这条shell所代表的意思:
ls xxx.txt 2>&1 >/dev/null &
它表示:将ls xxx.txt这个操作的错误输出重定向到屏幕上,操作的标准输出重定向到/dev/null中。最后的&表示让程序在后台执行。
>/dev/null , 实际上可换成 1>/dev/null;重定向符号>默认是将1重定向 ,表示将标准输出重定向到/dev/null中。
例子2:
ls xxx.txt >/dev/null 2>&1 &
例子2表示:标准错误输出和标准输出都定向到/dev/null中.
为什么2>&1一定要写到>/dev/null后面,才表示标准错误输出和标准输出都定向到/dev/null中?
我们不妨把1和2都理解是一个指针.
这样例子1的语句(ls xxx.txt 2>&1 >/dev/null &)我们可以这样分析:
本来1-------------》屏幕
2>&1 :标准错误输出重定向到标准输出,2---------》1
>/dev/null :替换成1>/dev/null,1-------》/dev/null
所以最后就变成了:2->屏幕,1->/dev/null,
例子2的语句(ls xxx.txt >/dev/null 2>&1 &)我们可以这样分析:
本来1-------------》屏幕
>/dev/null :替换成1>/dev/null,1-------》/dev/null
2>&1 :标准错误输出重定向到标准输出,2---------》1
所以最后就变成了:1->/dev/null,2->/dev/null
每次都写">/dev/null 2>&1"太麻烦,能简写吗?
有以下两种简写方式,但是一般我们都>log 2>&1这样写,只作为了解
&>/dev/null
>&/dev/null
=====================================================================
```
uci shell 接口:
注:以"uci_"开头的函数和以“config_”开头的函数大多数功能完全相同,唯一不同的是uci_get等函数直接从文件中获取,“config_get”函数从环境变量中读取
/lib/config/uci.sh
#参考对应的命令实现
1.uci_load #从uci文件中加载配置并设置到环境变量中
2.uci_set_default
3.uci_revert_state
4.uci_set_state()
5.uci_toggle_state
6.uci_set
7.uci_get_state #指定从/var/state中获取状态值
8.uci_get #从uci文件中获取值
9.uci_add
10.uci_rename
11.uci_remove
12.uci_commit
/lib/functions.sh
注意:在使用“config_”开头的函数时要先使用config_load,将配置文件载入环境变量
config:配置节
section:配置节后面接的那个东东,如下interface
option:配置节中的选项
list:配置节中的链表
例子:
config interface 'wan'
option enabled '1'
option track_ip 'www.baidu.com 8.8.8.8'
1.config_unset <section> <option> //清空 <section>.<option> value值
2.config_load <config> //从配置文件中读取配置然后设置到环境变量中
3.config_get <var> <section> <option> [<default>]
//var:用来存储config值的变量,section/option:要获取节点/选项的名字
4.config_set <section> <option> <value> //将变量设置到环境变量中以便后续读取(注意:并未设置到配置文件中)
5.config_foreach <callback_func> [<section type>] //遍历section type作为参数去执行回调函数
6.config_list_foreach <section> <list> <callback_func> //遍历section下list的option值作为参数调用回调函数
7.insert_modules //加载/etc/modus.d/*下面的所有模块
```
```
mwan3_count_one_bits()
{
local count n
count=0
n=$(($1))
while [ "$n" -gt "0" ]; do
n=$((n&(n-1)))
count=$((count+1))
done
echo $count
}
通过传入一个十进制数n,可以算出这个数的二进制有多少个1.
方法:
count = 0;
while(n>0)
{
n=n&(n-1);
count++;
}
因为循环执行n=n&(n-1),最终会执行最开始n的二进制中1的个数次然后变为0.
```
```
AWK:awk是linux一种处理文本数据的工具
awk命令和sed命令类似,也是逐行扫描文件,寻找含有目标文本的行(没有在命令行中指定文件名,awk 程序需要用户输入获得数据),如果匹配成功,就会在该行上执行用户想要的操作。
awk命令基本格式:
awk [选项参数] '脚本命令' 文件名
常用选项:
-F fs //指定以fs作为输入行的分隔符,awk命令默认分隔符为空格或制表符(\t)
-f file //从脚本文件中读取awk脚本命令,以取代在命令行中输入指令
-v var=val //在处理过程之前,设置一个变量var,并给其设置初始值为val
脚本命令:
awk的强大之处在于组成它的脚本命令,这个脚本命令由2部分组成,分为匹配规则和执行命令,如下所示:
'匹配规则{执行命令}'
匹配规则,用来指定可以作用到文本内容中的具体行,可以使用字符串或者正则表达式指定:
例如:/demo/,表示查看含有demo字符串的行
例子:[root@localhost ~]# awk '/^$/ {print "Blank line"}' test.txt
/^$/,/^$/是一个正则表达式,功能是匹配空白行,执行命令使用的是 print 命令,此命令经常会使用,它的作用很简单,就是将指定的文本进行输出。因此,整个命令的功能是,如果 test.txt 有 N 个空白行,那么执行此命令会输出 N 个 Blank line。
注意:
1.整个脚本命令是用单引号 ' ' 括起,而其中执行命令部分需要用大括号({})括起来。
2.awk程序执行时,如果没有指定执行命令,则默认会把匹配的行输出;如果不指定匹配规则,则默认匹配文本中的所有行。
默认情况下,awk会将如下变量分配给它在文本行中发现的数据字段(awk处理数据默认以行为单位):
$0:代表整个文本行
$1:代表文本行中的第1个数据字段
$2:代表文本行中的第2个数据字段
$n:代表文本行中的第n个数据字段
awk处理文本行分隔符(默认以空格或制表符作为行分隔符,可以使用-F参数手动指定):
例子:
$ awk -F, '{print $1,$2}' log.txt //以,作为分隔符,打印文本行的第一和第二个数据
在文本行中,每个数据字段都是以字段分隔符进行划分的,awk默认以空格或制表符为分隔符,如果需要指定其它分隔符,可以使用-F选项手动指定。
例子:假如现在有一个文件,data.txt,我们使用awk读取文本文件实现显示每一行的第1个数据字段的值。
[root]#cat data.txt
One line of test text.
Two lines of test text.
Three lines of test text.
[root]#awk '{print $1}' data2.txt
One
Two
Three
awk脚本命令如何使用多个命令:(加分号 ;隔开命令)
例子:
awk 允许将多条命令组合成一个正常的程序。要在命令行上的程序脚本中使用多条命令,只要在命令之间放个分号即可,例如:
[root@localhost ~]# echo "My name is Rich" | awk '{$4="Christine"; print $0}'
My name is Christine
第一条命令会给字段变量 $4 赋值。第二条命令会打印整个数据字段。可以看到,awk 程序在输出中已经将原文本中的第四个数据字段替换成了新值。
awk在文件中读取命令(使用 -f 文件名,表示使用文件中的命令)
例子:
[root@localhost ~]# cat awk.sh
{print $1 "'s home directory is " $6}
[root@localhost ~]# awk -F: -f awk.sh /etc/passwd
root's home directory is /root
bin's home directory is /bin
daemon's home directory is /sbin
adm's home directory is /var/adm
lp's home directory is /var/spool/lpd
```
awk BEGIN关键字:(BEGIN 会强制 awk 在读取数据前执行该关键字后指定的脚本命令)
例子:
[root@localhost ~]# cat data3.txt
Line 1
Line 2
Line 3
[root@localhost ~]# awk 'BEGIN {print "The data3 File Contents:"}
> {print $0}' data3.txt
The data3 File Contents:
Line 1
Line 2
Line 3
可以看到,这里的脚本命令中分为 2 部分,BEGIN 部分的脚本指令会在 awk 命令处理数据前运行,而真正用来处理数据的是第二段脚本命令。
awk END关键字:(和 BEGIN 关键字相对应,END 关键字允许我们指定一些脚本命令,awk 会在读完数据后执行它们)
例子:
[root@localhost ~]# awk 'BEGIN {print "The data3 File Contents:"}
> {print $0}
> END {print "End of File"}' data3.txt
The data3 File Contents:
Line 1
Line 2
Line 3
End of File
可以看到,当 awk 程序打印完文件内容后,才会执行 END 中的脚本命令。