shell && 正则表达式

目录

 

一.shell概述

1.概述

2.使用方法

二.shell语法

1.shell变量

1)局部变量

2)全局变量(可以在当前shell进程中使用)

3)环境变量 (可以在shell子进程中使用)

2.字符替换、命令替换、算术代码和转义字符

3.位置参数和特殊变量

4.输入和输出

5.条件判断表达式(真:0;假:1)

6.逻辑运算

7.条件语句

1)if分支语句

2)case分支语句

 

8.循环语句

1)for循环语句(6种模型)

2)while循环语句

9.控制语句

10.数组

11.函数

12.shell调试

三.正则表达式


一.shell概述

1.概述

shell是一个用于用户和LInux系统之间交互的命令解释器

shell有两种模式:

交互式:用户输入一条命令,shell就解释执行一条。

非交互式:用户事先写一个shell脚本,其中有很多条命令,让shell一次把这些命令执行完,而不是一条一条地敲命令

2.使用方法

  1. vim xx.sh
  2. 在第一行输入#!/bin/bash  //声明shell类型 bash shell,可以省略不写。
  3. 编写命令 保存退出
  4. 使用chmod 可执行权限 (可以bash xx.sh 不需要更改权限)
  5. 运行./xx.sh  或  bash xx.sh
  6. #为注释

二.shell语法

$使用:${}--取变量内容       $()--取命令执行结果      $[] 或者$(())--算数运算

1.shell变量

1)局部变量

shell脚本内定义的变量默认是全局变量,如果只想在某个函数内部使用,添加关键词local

2)全局变量(可以在当前shell进程中使用)

变量定义:test=aaa

变量赋值:test=bbb  

变量追加 : test+=ccc  //bbbccc

变量拼接:test=${test}.ddd

变量使用:echo ${test} 或 echo $test

清空变量:unset test

变量第一次出现是定义,之后是变量的赋值

3)环境变量 (可以在shell子进程中使用)

环境变量 :操作系统运行必要的变量,在操作系统开机时就已经定义好了。对所有的shell都生效。

用 echo $PWD 显示,

用 env 查看所有环境变量,

用 env | grep "name"查找指定环境变量。

用"export"进行设定或更改为环境变量

修改环境变量:export PATH=$PATH:/root   //将root用户添加PATH环境变量里,重启后失效(PATH内保存的是bin目录--用户命令)

注意:不同的终端拥有各自独立的环境变量,shell变量不需要先定义,随用随定,初始化不赋值默认为空字符串。

 

单引号:括字符串——不能展开变量

双引号:括字符串——可以将变量展开     建议,在取变量值时,都加""

              

 

2.字符替换、命令替换、算术代码和转义字符

字符替换:

*:匹配0个或多个任意字符 *.sh

?:一个?代表匹配一个字符

[]:匹配任意一个字符  [a-z][0-9].sh   其中数字只能匹配单个【0-9】,如果想匹配多位数【1-3】【0-9】= 10-39

命令替换:

test=$(data)  或 test=`data` ESC下面的反单引号

算术代码:

$((变量名))      :对变量执行算数运算

$[变量名]         :对变量执行算数运算

示例:$((VAR+10))          或              $[VAR+10]

注意:只能进行整数运算

   

转义字符:

’\’在Shell中被用作转义字符,用于去除紧跟其后的单个字符的特殊意义(回车除外)

3.位置参数和特殊变量

$0相当于argc[0],对于shell来说永远都是shell脚本
$1 $2..相当于传参的argc[1] argc[2]....
$#相当于argv-1  传参个数
$@=$*表示参数列表所有值
$?上一条命令执行完后的 结果存放在此
$$当前进程号

4.输入和输出

输入:read test

输出:echo [opt] string

-e:解析转义字符

-n:不回车换行  echo默认回车换行

5.条件判断表达式(真:0;假:1)

大于-gt(greater than)
大于等于-ge(greater equal)
小于-lt(less than)
小于等于-le(less equal)
等于-eq(equal)
不能等于-ne(not equal)

如果DIR存在并且是一个目录则为真

[ -d DIR ]
如果FILE存在并且是一个普通文件则为真[ -f FILE ]
判断文件是否存在,如果存在则为真[ -e FILE ]
如果STR的长度为0则为真[ -z STR ]

如果STR的长度非0则为真

[ -n STR ]
如果俩个字符串相同则为真[ str1 = str2 ]
如果字符串不相同则为真[ str1 != str2 ]

注:只要涉及条件表达式各个符号之间一定要有空格

6.逻辑运算

-a :逻辑与

-o:逻辑或

!:逻辑非

优先级:非 > 或 > 与

7.条件语句

1)if分支语句

if [ 条件 ];then
    执行内容
fi

if [ 条件 ]
then
    执行内容
fi

if [ 条件 ]
then
    执行内容
elif [ 条件 ]
then
    执行内容
else
    执行内容
fi 

#!/bin/bash
echo "请输入你要判别的文件名"
read file_name
if [ -f $file_name ];then
	echo "It is a file"
elif [ -d $file_name ];then
	echo "It is a dir"
else
	echo "It is not a know file"	
fi

2)case分支语句

case &变量 in

case1)

执行语句;;

case2)

执行语句;;

.......

*)

执行语句;;

esac

#!/bin/bash

read score

case ${score} in
	0|60)
		echo "0或者60";; //0或者60
	[6-8][0-9]) 
		echo "合格";; //60-89
	[9][0-9]|100)
		echo "优秀";;  //90-99 100
	esac

 

#!/bin/bash
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
case "$YES_OR_NO" in
yes|y|Yes|YES)
		echo "Good Morning!"
        echo "Good Morning!"
        echo "Good Morning!;;
[nN][Oo])
		echo "Good Afternoon!";;
*)
		echo "Sorry,$YES_OR_NO not recognized.Enter yes or no";;
esac

8.循环语句

1)for循环语句(6种模型)

Shell脚本中的for循环还可以实现在列表中循环一遍(遍历列表)。从这个列表中拿值

语法循环

for((i=0;i<5;i++))

do

         执行内容

done

有限数字

#!/bin/bash

for A in 1 2 3 4 5 6

do

         echo $A

done

 

命令结果$

#!/bin/bash

IFS=$`\n`

for A in $(cat ./2.sh)   #取命令执行结果作为集合

do

         echo $A

done

序列数据

#!/bin/bash

for A in $(seq 1 1 10)   #取命令执行结果作为集合

do

         echo $A

done

集合:{}表示一个连续序列

#!/bin/bash

for A in {a..z}

do

         echo $A

done

变量作为集合

#!/bin/bash

buff="1 2 3 4 5 6 7 8 9"

for A in $buff

do

         echo $A

done

求1-100和
#!/bin/bash
sum=0

for i in $(seq 1 100)
do
	sum=$((sum+i))
	if [ ${i} -eq 100 ];then
		echo "${sum}"
		exit 0
	fi
done
#!/bin/bash
for FRUIT in apple banana pear;do
	echo "I like $FRUIT"
done

2)while循环语句

while [ 循环条件 ]

do

         执行内容

done

#!/bin/bash
echo "Enter password:"
read TRY
while [ "$TRY" != "123123" ];do
	echo "Sorry,try again"
	read TRY
done

9.控制语句

break :可以跳出循环;

continue:跳过本次循环,但不会跳出循环。

exit:结束本程序,结束进程

10.数组

数组定义:a=(1 2 3 4 5)   或者 a[0]=1;a[1]=2;a[2]=3;

数组引用:${a[下标]}

数组长度:${#a[@]} 或 ${#a[*]}

#!/bin/bash
a=(3 10 6 5 9 2 8 1 4 7)
i=0
echo ${#a[*]}
while [ $i -lt 10 ] 	#类似C语言的写法
do
 		echo ${a[$i]}
 		i=$((i+1))
done

11.函数

函数名()

{

         函数体

}

function 函数名()

{

         函数体

}

参数:函数外:$0--命令行参数argc[0]

                         $1-$N--命令行参数的argc[1]-argc[N]

           函数内:

                          $0--命令行参数argc[0]

                          $1-$N--函数的参数1--参数N

返回值:用$?接收 只能返回某个0-255之间的整数值

调用:函数名即可,不加括号

#!/bin/bash

A=$1
B=$2

add()
{
	return $((A+B))
}
sub()
{
	return $((A-B))
}
mul()
{
	return $((A*B))
}
div()
{
	return $((A/B))
}
//add 2 1 脚本内传参
add
	echo $?
sub
	echo $?
mul
	echo $?
div
	echo $?

注:函数定义必须在调用之前,且不能声明

12.shell调试

-n

读一遍脚本中的命令但不执行,用于检查脚本中的语法错误

-v

一边执行脚本,一边将执行过的脚本命令打印到标准错误输出

-x

提供跟踪执行信息,将执行的每一条命令和结果依次打印出来

调试模板:sh -x 可执行文件

如果出现无反应问题:代码对于标准bash而言没有错,因为Ubuntu/Debian为了加快开机速度,用dash代替了传统的bash,是dash在捣鬼,解决方法就是取消dash。

sudo dpkg-reconfigure dash

选择项中选No,搞定了!

-n示例:

 

#!/bin/bash

#:#代表注释功能

#IFS说明:bash shell 会将空格、制表符、换行当做分隔符

#定义该函数     先定义再调用

function func(){

       echo "我是func函数"

       echo "函数体内参数0$0"

       echo "函数体内参数1$1"

       echo "函数体内参数2$2"

       echo "函数体内参数3$3"

       return xyd

}

#调用函数

A=$(func one two three)

echo "A结果${A}"

echo "./1.sh参数0$0"

echo "./1.sh参数1$1"

echo "./1.sh参数2$2"

echo "./1.sh参数3$3"

if["xyd"="xyd"];then

       echo "xyd"

fi

echo  "结束"

效果:

-v调试

#!/bin/bash

#:#代表注释功能

#IFS说明:bash shell 会将空格、制表符、换行当做分隔符

#定义该函数     先定义再调用

function func(){

       echo "我是func函数"

       echo "函数体内参数0$0"

       echo "函数体内参数1$1"

       echo "函数体内参数2$2"

       echo "函数体内参数3$3"

       return xyd

}

#调用函数

A=$(func one two three)

echo "A结果${A}"

echo "./1.sh参数0$0"

echo "./1.sh参数1$1"

echo "./1.sh参数2$2"

echo "./1.sh参数3$3"

 

if [ "xyd" = "xyd" ];then

       echo "xyd"

fi

echo  "结束"

效果:

 

 

三.正则表达式

1.grep与find命令

1)grep

grep是一个强大的文本搜索器。grep命令用于在指定文件中搜索包含与给定PATTERN匹配的行。如果gerep未指定文件或者为-,则grep指令会从标准输入设备读取数据。默认情况下,grep打印的是符合条件所在的行。默认下grep使用的是基础正则表达式,使用egrep或grep -E指定的是扩展正则表达式。

grep家族有:grep、egrep、fgrep。egrep、fgrep分别与grep –E(扩展正则表达式) rep -r相同。

常用格式:grep [OPTIONS] PATTERN [FILE] 

              --help:获取更多信息。

              -i:不区分大小写。

              -n:显示匹配行及行号。

              -v:显示不包含匹配文本的所有行。

              -c:只输出匹配行的计数。不打印行内容打印行号

              -o:只显示被模式匹配到的字符串。打印想要的内容,可能对打出涵盖单词的字符串

              -w:被匹配的文本只能是单词,而不能是单词中的某一部分。只打印想要的内容

              -E :开启扩展(Extend)的正则表达式。

              -h:查询多文件时不显示文件名。

              -l:查询多文件时只输出包含匹配字符的文件名。

              -L:查询多文件时只输出不包含匹配字符的文件名。       

        -A  n:显示匹配到的字符串所在的行及其后n行,after

       -B  n:显示匹配到的字符串所在的行及其前n行,before

       -C  n:显示匹配到的字符串所在的行及其前后各n行,context

2)find

find 命令用来在指定目录下查找文件,并且搜索完成后可以执行相应的操作,搜索时我们可以根据参数指定相应的搜索条件,比如按文件名,文件类型,时间戳等。find命令的基本格式如下所示:

常用格式:find [path] [option] [expression] 

注:如果使用find命令不设置任何参数,则find命令将在当前目录下查找子目录和文件,并打印

根据文件名字查找文件:     -name

 

# find ./ -name "testfile"                    #查找名字为testfile的文件

# find ./ -iname "testfile"                   #查找名字为testfile的文件,忽略大小写

# find ./ -name "*.c"                           #查找名字以“.c

根据文件大小查找文件:     -size

# find ./ -size 5c                                    #查找文件大小为5个字节的文件

# find ./ -size +5k                                  #查找文件大小大于5KB的文件

# find ./ -size -5M                                 #查找文件大小小于5MB的文件

# find ./ -size +5G -size -10G             #查找文件大于5GB小于10GB的文件

文件类型查找文件:     -type     find ./ -type f   

f:普通文件             d:目录文件            l:链接文件             p:管道文件

b:块设备文件       c:字符设备文件   s:套接字文件

 

限制目录查找深度:                   -maxdepth

find命令默认会递归查找整个目录树

# find ./ -maxdepth 2 -type d                 #在两层以内的子目录中查找文件类型为目录文件的文件

查找到的文件执行命令:-exec|-ok

find ./ -maxdepth 2 -tpye d -exec ls -l {} \;表示结束  固定格式

find -maxdepth 1 -type f | -ok ls -l {} \;    

根据时间查找文件:                   -atime|-mtime|-ctime|-amin|-mmin|-cmin

atime:访问时间(access time),指的是文件内容最后被访问的时间,单位为天。

mtime:修改时间(modify time),指的是文件内容最后被修改的时间,单位为天。

ctime:变更时间(change time),指的是文件本身最后被变更的时间,这个变更是指文件内容发生修改或者文件权限,路径发生改变,单位为天。

amin|mmin|cmin:单位为分钟

# find ./ -mtime -3                                     #查找三天内修改过的文件

# find ./ -atime 3                                  #查找过去的第三天被修改的文件

# find ./ -mtime +3                               #查找三天前修改过的文件

文件权限查找文件:          -perm

# find ./ -perm 0644                            #查找文件权限为0644的文件

# find ./ -perm -0644                           #查找文件权限至少是0644的文件

# find ./ -perm /0644                           #查找文件权限至少是0644中的一种权限的文件。

根据文件属主查找文件:          -user

# find ./ -user root                                    #查找文件属主为root的文件

根据文件属组查找文件:          -group

# find ./ -group root                        #查找文件属组为root的文件

3)正则表达式命令

正则表达式分为基础正则表达式和扩展正则表达式。

正则表达式是对普通字符和特殊字符(元字符)操作的一种逻辑公式。就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。

元素种类元字符元字符功能
字符匹配.匹配任意字符
[]

两者连用表示取序集

【a-zA-Z0-9】

-
^放在【】里,表示取除了括号内的任意字符’
\转义
次数匹配

表示匹配?前面单元0或1次

egrep "12?" 2.txt :匹配的是1或者2或者12

egrep "(12)?" 2.txt:匹配的是12
 

+匹配前面单元1次或者多次
*匹配前面单元0次或者多次
{N}匹配前面单元N次
{,M}匹配前面单元最多M次
{N,M}匹配前面单元最少N次,最多M次

位置铆定

 

^匹配行首位置,放在正则表达式开头
 $匹配行尾位置,放在正则表达式结尾
 

\<匹配单词开头的位置
\>匹配单词结尾的位置

 

root@turbo:/home/xyd/study/Regular# egrep "\<a" 2.txt
aaaada
root@turbo:/home/xyd/study/Regular# egrep "a\>" 2.txt
aaaada

 
 \b

匹配单词开头或结尾的位置

root@turbo:/home/xyd/study/Regular# egrep "a\b" 2.txt
aaaada
root@turbo:/home/xyd/study/Regular# egrep "\ba" 2.txt
aaaada

 \B

根据\B的位置去匹配非单词开头或结尾的位置,如果放在正则表达式开头,就是非开头,却不包括结尾。

root@turbo:/home/xyd/study/Regular# egrep "\Ba" 2.txt
aaaada

 ()括号匹配的是一个单元
 匹配汉字

grep -P "[\p{Han}]" text.c

egrep "[\u4e00-\u9fa5]+ [\u4e00-\u9fa5]*" "1.txt"

[[:alpha:]]

:匹配任意大小写字母

egrep [[:alpha:]] 2.txt

[[:alnum:]]:

匹配字母与数字

[[:upper:]]:

匹配任意大写字母

[[:space:]]:

匹配空格
[[:digit:]]:匹配十进制数字

[[:punct:]]:

匹配标点符号

4)C语言正则表达式

C语言正则表达式常用的函数有regcomp(),regexec(),regfree(),regerror()

大题流程:regcomp编译正则表达式,regexec匹配正则表达式,regfree()释放正则表达式

int regcomp(regex_t *preg,const char *regec,int cflags)

功能:把指定的正则表达式pattern编译成一种特定的数据格式preg,这样可以使匹配更有效。

参数:

preg:    用来存放编译后的正则表达式

regex:    指向我们写好的正则表达式

cflags:有如下4个值或者是它们或运算(|)后的值
        REG_EXTENDED--以功能更加强大的扩展正则表达式的方式进行匹配。
        REG_ICASE-----匹配字母时忽略大小写。
        REG_NOSUB-----不用存储匹配后的结果。
        REG_NEWLINE---识别换行符,这样'$'就可以从行尾开始匹配,'^'就可以从行的开头开始匹配

返回值:成功返回0,失败返回错误码
 

int regexec(const regex_t *preg,const char *string,size_t nmatch,regmath_t pmatch[],int eflags)

功能:接收匹配得到的数据。

例如:如果nmatch给定长度为2,那么regmatch_t 就是两个结构体数组。第一个结构体数组存放第一个匹配成功字符串信息。第
二个返回第二个匹配成功字符串信息。

参数:
    preg:    是已经用regcomp函数编译好的正则表达式
    string:是目标文本串
    nmatch:是regmatch_t结构体数组的长度
    pmatch:regmatch_t类型的结构体数组,存放匹配文本串的位置信息
    eflags:有两个值
        REG_NOTBOL:让特殊字符^无作用
        REG_NOTEOL:让特殊字符$无作用
返回值:成功返回0,失败返回REG_NOMATCH

typedef struct {
    regoff_t rm_so;        //存放匹配文本串在目标串中的开始位置
    regoff_t rm_eo;        //存放匹配文本串在目标串中的结束位置
} regmatch_t;

void regfree(regex_t *preg)

功能: 当我们使用完编译好的正则表达式后,或者要重新编译其他正则表达式的时候,我们可以用这个函数清空compiled指向的

regex_t结构体的内容, 请记住,如果是重新编译的话,一定要先清空regex_t结构体。

preg:    是已经用regcomp函数编译好的正则表达式

size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)

功能:当执行regcomp 或者regexec 产生错误的时候,就可以调用这个函数而返回一个包含错误信息的字符串

参数:
    errcode:是由regcomp 和 regexec 函数返回的错误代号。
    preg:     是已经用regcomp函数编译好的正则表达式,这个值可以为NULL。
    errbuf: 指向用来存放错误信息的字符串的内存空间。
    errbuf_size:指明buffer的长度,
        注:如果这个错误信息的长度大于这个值,则regerror 函数会自动截断超出的字符串,
        但他仍然会返回完整的字符串的长度。所以我们可以用如下的方法先得到错误字符串的长度。
        size_t length = regerror (errcode, compiled, NULL, 0);
返回值:返回错误信息字符串的长度

#include<stdio.h>
#include <sys/types.h>
#include <regex.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argv,char *argc[])
{
	if(argv < 2)
	{
		perror("argv");
		exit(0);
	}
	const char *regular= argc[1];
	const char *string= argc[2];
	regex_t preg;
	int comp_code = regcomp(&preg,regular,REG_EXTENDED) ;
	if(comp_code != 0)
	{
		perror("regcomp");
		exit(0);
	}
	regmatch_t pmatch[1];
	int exec_code = regexec(&preg,string,1,pmatch,0);//数组长度为1
	if(exec_code == 0)
	{
	//	printf("%s match  %s\n",string,regular);
		int i = 0;

		for(i = pmatch[0].rm_so;i < pmatch[0].rm_eo; i ++)
		{
			printf("%c",*(string + i));
		}
		printf("\n");
		regfree(&preg);
		return 0;
	}



	char buff[256] = {0};
	size_t err_len = (comp_code,preg,buff,256);
	err_len = err_len < sizeof(err_len) ? err_len:sizeof(err_len -1);
	buff[err_len+1] = '\0';
	printf("%s \n",buff);
	regfree(&preg);
	
	
    return 0;
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值