继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

详解Linux Shell(函数与sed)

侠客岛的含笑
关注TA
已关注
手记 133
粉丝 1.6万
获赞 1807

函数

  • 直接使用函数名调用,可以将其想象成Shell中的一条命令
  • 函数内部可以直接使用参数$1、$2...$n
  • 调用函数:function name $1$2
#!/bin/bash
this_pid=$$
status=`ps -ef | grep nginx | grep-v grep | grep -v $this_pid &> /dev/null`
if  [$status == 0];then
	echo "Nginx is running well"
	sleep 60
else
	systemc start nginx
	echo "Nginx is down,Start it...."
fi

向函数传递参数:
函数传参和给脚本传参类似,都是使用$1$2$3$4$5$6$7这种方式

#!/bin/bash
function calcu
{
	case $2 in
			+)
				echo "expr $1+$3"
				;;
			-)
				echo "expr$1-$3"I
				;;
			\*)
				echo "expr $1\*$3"
				;;
			/)
				echo "expr $1/$3"
				;;
	esac
}
calcu $1 $2 $3

返回值的形式

  • return
    • 使用return返回值,只能返回1-255的整数
    • 函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败
  • echo
    • 使用echo可以返回任何字符串结果
    • 通常用于返回数据,比如一个字符串值或者列表值
#!/bin/bash
this_pid=$$
function is_nginx_running
{
	ps-ef | grep nginx | grep -v grep | grep-v Sthis_pid s>/dev/null
	if[ $? -eq 0];then
		return
	else
		return 1
	fi
}
if_nginx_ running && echo "Nginx is running " || echo "Nginx is stoped"
#!/bin/bash

function get users
{
	users=`cat /etc/passwd | cut -d: -f1`
	echo $users
}
user_list=`get_users`
index=1
for u in $user_list
do
	echo "The $index user is:$u"
	index=$(($index+1))
done


局部变量和全局变量

  • 不做特殊声明,Shell中变量都是全局变量
    • Tips:大型脚本程序中函数中慎用全局变量
  • 定义变量时,使用local关键字
  • 函数内和外若存在同名变量,则函数内部变量覆盖外部变量

函数库

  • 经常使用的重复代码封装成函数文件
  • 一般不直接执行,而是由其他脚本调用
function sys load
{
	echo "Memory Info"
	echo
	free-m
	echo
	echo "Disk Usage"I
	echo
	df-h
	echo
}
  • 库文件名的后缀是任意的,但一般使用.lib
  • 库文件通常没有可执行选项
  • 库文件无需和脚本在同级目录,只需在脚本中引用时指定
  • 第一行一般使用#!/bin/echo,输出警告信息,避免用户执行

find

  • -name 根据文件名查找
  • -perm 根据文件权限查找
  • -prune 该选项可以排除某些查找目录
  • -user 根据文件属主查找
  • -group 根据文件属组查找
  • -mtime -n|+n 根据文件更改时间查找
  • -nogroup 查找无有效属组的文件
  • -nouser 查找无有效属主的文件
  • -newer file1!file2 查找更改时间比file1新但比file2旧IDE文件
  • -type 按文件类型查找
  • -size-n+n 按文件大小查找
  • -mindepth n 从n级子目录开始搜索
  • -maxdepth n 最多搜索到n级子目录
    图片描述
#prune通常和-path一起使用,用于将特定目录排除在搜索条件之外
#例子1:查找当前目录下所有普通文件,但排除test目录
find . -path ./etc -prune -o -type f
#例子2:查找当前目录下所有普通文件,但排除etc和opt目录
find .-path./etc -prune -o -path./opt -prune-o-type f
#例子3:查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs
find . -path ./etc -prune -o -path ./opt -prune -o -type f -a -user hdfs
#例子4:查找当前目录下所有普通文件,但排除etc和opt目录,但属主为hdfs,且文件大小必须大于500字
find . -path ./etc -prune -o -path ./opt -prune -o-type f -a -user hdfs -a -size +500c
  • -print打印输出
  • -exec对搜索到的文件执行特定的操作,格式为-execcommand’{}\;
    • 例子1:搜索/etc下的文件(非目录),文件名以conf结尾,且大于10k,然后将其删除
      • find ./etc/ -type f-name '*.conf' -size +10k -exec rm -f {} \;
    • 例子2:将/var/1og/目录下以1og结尾的文件,且更改时间在7天以上的删除
      • find /var/log/ -name '*.log' -mtime +7-exec rm -rf {} \
    • 例子3:搜索条件和例子1一样,只是不删除,而是将其复制到/root/conf目录下
      • find ./etc/ -size +10k -type f -name '*.conf' -exec cp {} /root/conf/ \;
  • -ok和exec功能一样,只是每次操作都会给用户提示

  • -a 与
  • -o 或
  • -notl!非

例子1:查找当前目录下,属主不是hdfs的所有文件

find . -not -user hdfs | find . ! -user hdfs

例子2:查找当前目录下,属主属于hdfs,且大小大于300字节的文件

find . -type f -a -user hdfs -a -size +300c

例子3:查找当前目录下的属主为hdfs或者以xm1结尾的普通文件

find . -type f -a \(-user hdfs -o -name '*.xml'\)

locate

  • 文件查找命令,所属软件包mlocate
  • 不同于find命令是在整块磁盘中搜索,locate命令在数据库文件中查找
  • find是默认全部匹配,locate则是默认部分匹配

updatedb

  • 用户更新/var/lib/mlocate/mlocate.db
  • 听使用配置文件/etc/updatedb.conf
  • 该命令在后台cron计划任务中定期执行

whereis

  • -b 只返回二进制文件
  • -m 只返回帮助文档文件
  • -s 只返回源代码文件

which

作用:仅查找二进制程序文件
-b 只返回二进制文件


  • find 查找某一类文件,比如文件名部分一致 功能强大,速度慢
  • locate只能查找单个文件功能单一,速度快
  • whereis 查找程序的可执行文件、帮助文档等不常用
  • which 只查找程序的可执行文件常用于查找程序的绝对路径

sed

  • sed(Stream Editor),流编辑器。对标准输出或文件逐行进行处理
    • 第一种形式:stdout | sed [option] “pattern command”
    • 第二种形式:sed [option] “pattern command” file

  • -n 只打印模式匹配行
  • -e 直接在命令行进行sed编辑,默认选项
  • -f 编辑动作保存在文件中,指定文件执行
  • -r 支持扩展正则表达式
  • -i 直接修改文件内容

sed pattern

  • 10command 匹配到第10行
  • 10,20command 匹配从第10行开始,到第20行结束
  • 10,+5command 匹配从第10行开始,到第16行结束
  • /pattern1/command 匹配到pattern1的行
  • /pattern1/,/pattern2/command 匹配到pattern1的行开始,到匹配到pattern2的行结束
  • 10,/pattern1/command 匹配从第10行开始,到匹配到pettern1的行结束
  • /pattern1/,10command 匹配到pattern1的行开始,到第10行匹配结束
sed -n "17p" fi1e #打印file文件的第17行
sed -n "10,20p" file #打印file文件的10到20行
sed -n "10,+5p" file #打印file文件中从第10行开始,往后面加5行的所有行
sed -n "/^root/p" file #打印fi1e文件中以root开头的行
sed -n "/^ftp/,/^mail/p" file #打印fi1e文件中第一个匹配到以ftp开头的行,到第二个以mail开头的行
sed -n "4,/^hdfs/p" file #打印fi1e文件中从第4行开始匹配,直到以hdfs开头
sed -n "/root/,10p" file #打印fi1e文件中匹配root的行,直到第10行结束

编辑

  • 查询
    • p 打印
  • 增加
    • a 行后追加
    • i 行前追加
    • r 外部文件读入,行后追加
    • w 匹配行写入外部文件
  • 删除
    • d 删除
  • 修改
    • s/old/new 将行内第一个old替换为new
    • s/old/new/g 将行内全部的old替换为new
    • 修议s/old/new/2g 将行内前2个old替换为new(同一行内,只替换前2个匹配的,剩下的不替换)
    • s/old/new/ig 将行内old全部替换为new,忽略大小写
  • 其他
    • = 显示行号

什么是反向引用?

  • &和\1 引用模式匹配到的整个串
  • sed “s/1…e/&r/g” file 在file中搜寻以1开头,然后跟两个任意字符,以e结尾的字符串
  • sed “s/(1…e)/\1r/g” file 和上面实现一样的功能,使用\1代表搜寻到的字
  • 上面两种方式实现了一样的功能,分别使用&和\1引用前面匹配到的整个字符串
  • 两者区别在于**&只能表示匹配到的完整字符串**,只能引用整个字符串;而\1可以使用()对匹配到的字符串部分匹配

例如:如果我们仅想要替换匹配到的字符串的一部分,name必须使用**\1**这种方式,不能

查找test.txt文件中以1开头,紧接着跟两个任意字符,再接一个e的字符串。将找到的字符串中开头的文字替换成L

sed "s/1\(..e\)/L\1/g" test.txt
  • 匹配模式中存在变量,则建议使用双引号
  • sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号

修道场

#1、打印/etc/passwd中第20行的内容
sed -n '20p' /etc/passwd
#2、打印/etc/passwd中从第8行开始,到第15行结束的内容
sed -n '8,15p' /etc/passwd
#3、打印/etc/passwd中从第8行开始,然后+5行结束的内容
sed -n '8,+5p' /etc/passwd
#4、打印/etc/passwd中开头匹配hdfs字符串的内容
sed -n '/^hdfs/p' /etc/passwd
#5、打印/etc/passwd中开头为root的行开始,到开头为hdfs的行结束的内容
sed -n '/^root/,/^hdfs/p' /etc/passwd
#6、打印/etc/passwd中第8行开始,到含有/sbin/nologin的内容的行结束内容
sed -n '8,/\/sbin\/nologin/p' /etc/passwd
#7、打印/etc/passwd中第一个包含/bin/bash内容的行开始,到第5行结束的内容
sed -n '/\/bin\/bash/,5p' /etc/passwd
#!/bin/bash
FILE NAME=/root/lesson/5.6/my.cnf
function get_all_segments
{
	echo "`sed -n '/\[.*\]/p' my.cnf | sed -e 's/\[//g'-e's/\]//g'`"
}
for seg in get all segments
echo " 配置项:$seg"
done

function count_items_in_segment
{
	items=`sed -n '/\['$1'\]/,/\[.*\]/p' $FILE_NAME | grep -v "^#" | grep -v "^$" | grep -v "\[.*\]"`
	index = 0
	for item in $items
	do 	
		index=`expr $index+1`
	done
	echo $index
}
number=0

for segment in `get_all_segements`
do
	number = `expr $number+1`
	items_count=`count_items_in_segment $segment`
	echo "$number: $segment $items_count" 
done
#1、删除/etc/passwd中的第15行
sed -i '15d' /etc/passwd
#2、删除/etc/passwd中的第8行到第14行的所有内容
sed- i  '8,14d' passwd
#3、删除/etc/passwd中的不能登录的用户(筛选条件:/sbin/nologin)
sed -i '/\/sbin\/nologin/d' passwd
#4、删除/etc/passwd中以mai1开头的行,到以yarn开头的行的所有内容
sed -i '/^mail/,/^yarn/d' passwd
#5、删除/etc/passwd中第一个不能登录的用户,到第13行的所有内容
sed -i '/\/sbin\/nologin/,13d' passwd
#6、删除/etc/passwd中第5行到以ftp开头的所有行的内容
sed -i '5,/^ftp/d' passwd
#7、删除/etc/passwd中以yarn开头的行到最后行的所有内容
sed -i '/^yarn/,$' passwd
#8、删除配置文件中的所有注释行和空行
sed -i '/[:blank:]*#/d;/^$/d' nginx.conf
#9、在配置文件中所有不以#开头的行前面添加*符号,注意:以#开头的行不添加
sed -i 's/^[#]/\*&/g' nginx.conf
打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP