shell笔记

这篇博客详细介绍了Linux Shell脚本中的比较运算符,包括整数和浮点数的比较,以及如何在单、双中括号和双小括号中使用。此外,还讲解了如何判断变量是否为空,以及使用`2>&1`进行标准输出和错误输出的重定向。文章最后提到了`uci_`和`config_`函数在配置管理中的应用,以及awk命令的使用,包括变量、模式匹配和脚本命令的组合。
摘要由CSDN通过智能技术生成

```
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 中的脚本命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值