shell判断语句
一、变量
1.变量的定义与赋值
基本规则
1,赋值符号为:=
2,调取变量时,变量前加:$
3,变量是命令时需要用执行符$()或``
示例1:
name="123" ;echo $name
123
示例2:
name=$(date +%F) ;echo $name
2019-04-16
注意事项
1,变量名和等号之间不能有空格
2,首个字符必须为字母(区分大小写)
3,中间不能有空格,不能用标点符号,只可以用下划线
4,不可使用bash中的系统变量
5,同名变量多次赋值,后面会覆盖前面的值
6,需要将变量与其他字符区分边界时,可使用{}或""
2.删除变量
命令:unset
语法:unset 变量
栗子:
赋值:name=10
删除:unset name
注意事项:
1,unset不能删除只读变量
3.变量替换
变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值
写法 | 说明 |
---|---|
${var} | 变量本来的值 |
${var:-word} | 如果变量 var 为空或已被删除(unset) ,那么返回 word ,但不改变 var 的值。 |
${var:=word} | 如果变量 var 为空或已被删除(unset) ,那么返回 word ,并将var 的值设置为 word 。 |
${var:+word} | 如果变量 var 被定义,那么返回 word ,但不改变 var 的值 |
${var:?message} | 如果变量 var 为空或已被删除(unset) ,那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。 若此替换出现在Shell 脚本中,那么脚本将停止运行。 |
4.特殊变量
特殊变量 | 含义 |
---|---|
$? | 当前脚本的文件名 |
$0 | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 |
$n | 传递给脚本或函数的参数个数。 |
$# | 传递给脚本或函数的所有参数。 |
$* | 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。 |
$@ | 上个命令的退出状态,或函数的返回值。 |
$$ | 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。 |
5.echo转义字符
echo选项
-e 使用转义字符
-E 禁止转义字符,默认就是不转义
转义字符 | 含义 |
---|---|
\\ | 反斜杠 |
\a | 警报,响铃 |
\b | 退格(删除键) |
\f | 换页(FF),将当前位置移到下页开头 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符(tab键) |
\v | 垂直制表符 |
二、函数
- 将一组命令集合或语句形成一个整体, 给这段代码起个名字称为函数名
1,函数的定义
方法1:
函数名() {
函数体(一堆命令的集合,来实现某个功能)
}
----------------------------------------
方法2:
function 函数名() {
函数体(一堆命令的集合,来实现某个功能)
}
*******************************************
举个栗子:
funct1() {
echo 1
echo 2
echo 3
}
2,函数的调用
funct1() { # 函数名加()来定义函数,小括号是固定写法,大括号里面为函数体
echo 1
echo 2
echo 3 # 大括号里的三条命令就是函数主体
}
funct1
直接使用函数名字调用函数,将会执行函数主体内的内容
3,函数的嵌套
funct1() {
echo 1
echo 2
}
funct2() {
funct1 # funct2里调用funct1,相当于是把funct1函数主体内的内容放到这个位置
echo 4
echo 5
}
funct2 # 调用funct2
三、运算符
1.算术运算
四则运算符 | 说明 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余数 |
** | 幂 |
2.算术运算的格式
1. 使用$[ ] (建议主用这种就可以了,其它可以看懂即可)
2. 使用 $(( ))
3. 使用expr外部程式
4. 使用let命令
5. 借助bc命令
栗子
#!/bin/bash
a=1
let a++ 使用let执行运算,后面变量前不用加$
b=$[$a-1]
c=$(($a**3))
d=`expr $a + 3` + 号两边要有空格
借助bc命令实现小数运算
# echo 1.1+2.2 | bc
3.3
# echo "sqrt(100)" | bc
10 求平方根
四、判断符号
一、判断语句格式
- 格式1: test 条件表达式
- 格式2: [ 条件表达式 ]
- 格式3: [[ 条件表达式 ]] 支持正则 =~
- F: false 假 T: true 真
格式示范
test -e /etc/fstab 判断文件是否存在
[ -d /etc ] 判断目录是否存在,存在条件为真 (中括号里面左边两边有空格)
[ ! -d /etc ] 判断目录是否存在,不存在条件为真 (中括号里面左边两边有空格)
[[ -f /etc/fstab ]] 判断文件是否存在,并且是普通文件 (中括号里面左边两边有空格)
# aaa=aaa123
# [[ $aaa =~ ^aaa ]]
# echo $?
0 返回值为0表示上面判断的aaa变量是以aaa开头
说明: man test去查看,很多的参数都用来进行条件判断
二、判断命令选项
1.文件类型的判断
判断参数 | 说明 |
---|---|
-e (常用) exist | 判断文件(任何类型文件)是否存在 |
-f (常用) file | 判断是否为普通文件 |
-d (常用) directory | 判断是否为目录 |
-S | 判断是否为socket文件 |
-p | 判断是否为pipe管道文件 |
-c | 判断是否为character字符设备文件 |
-b | 判断是否为block块设备 |
-L link | 判断是否为软链接 |
-s | 判断文件是否存在并且为非空文件 |
2.文件权限相关的判断
判断参数 | 说明 |
---|---|
-r | 当前用户对其是否可读 |
-w | 当前用户对其是否可写 |
-x | 当前用户对其是否可执行 |
-u | 是否有suid(权限9位的前3位里是否有s位) |
-g | 是否sgid(权限9位的中间3位里是否有s位) |
-k | 是否有t位(权限9位的后3位里是否有t位) |
3.两个文件的比较判断
判断表达式 | 说明 |
---|---|
file1 -nt file2 | 比较file1是否比file2新 |
file1 -ot file2 | 比较file1是否比file2旧 |
file1 -ef file2 | 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode |
4.整数之间的判断
判断参数 | 说明 |
---|---|
-eq | 相等 |
-ne | 不等 |
-gt | 大于 |
-lt | 小于 |
-ge | 大于等于 |
-le | 小于等于 |
5.字符串之间的判断
判断参数或表达式 | 说明 |
---|---|
-z | 是否为空字符串,字符串长度为0则为真 |
-n | 是否为非空字符串,只要字符串非空则为真 |
string1 = string2 | 两个字符串是否相等 |
string1 != string2 | 两个字符串是否不等 |
6.多重条件判断
判断参数 | |
---|---|
条件1 -a 条件2 (and) 条件1 && 条件2 | 两个条件同时满足,整个大条件为真 |
条件1 -o 条件2 (or) 条件1 || 条件2 | 两个条件满足任意一个,整个大条件为真 |
示例:
[ 1 -eq 1 -a 1 -ne 0 ] 整个表达式为真
[ 1 -eq 1 ] && [ 1 -ne 0 ]
[ 1 -eq 1 -o 1 -ne 1 ] 整个表达式为真
[ 1 -eq 1 ] || [ 1 -ne 1 ]
7.使用&&与||符号实现判断语句
符号 | 说明 |
---|---|
; | 不管前面执行是否正确,都会执行后面 |
&& | 前面执行正确,才会执行后面 |
|| | 前面执行失败,才会执行后面 |
条件 && 动作 # 前面条件满足则执行动作
条件 || 动作 # 前面条件失败则执行动作
条件 && 动作1 || 动作2 # 如果条件满足,则执行动作1,否则则执行动作2
示例:
# [ -e /etc/fstab ] && echo "文件存在" || echo "文件不存在"
文件存在
# [ -e /etc/sdfdsfdsa ] && echo "文件存在" || echo "文件不存在"
文件不存在
流程控制语句
一、if
1.单分支结构
实现:满足条件1,执行命令1
写法1:
if [ 条件1 ];then
命令1
fi
写法2:
[ 条件1 ] && 命令1
2.双分支结构
实现:满足条件1,执行命令1,不满足执行命令2
写法1:
if [ 条件1 ];then
命令1
else
命令2
fi
写法2:
[ 条件 ] && 命令1 || 命令2
3.多分支结构
实现:如果条件1满足,执行命令1后结束;
如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;
如果条件1和条件2都不满足执行命令3结束.
写法:
if [ 条件1 ];then
命令1
elif [ 条件2 ];then # 可以有多个elif
命令2
else
命令3
fi
实例:
#!/bin/bash
read -p "输入你的性别(man/woman):" sex
if [ $sex = man ];then
echo "帅哥"
elif [ $sex = woman ];then
echo "美女"
elif [ $sex = boy ];then
echo "小帅哥"
elif [ $sex = girl ];then
echo "小美女"
else
echo "性别输入有误"
fi
4. if嵌套
上面的三种分支结构可以互相嵌套,嵌套后的逻辑会比较复杂,实际写程序不宜嵌套过多(如果嵌套过多则说明你的逻辑不太好)
if [ 条件1 ];then
命令1
if [ 条件2 ];then
命令2
fi
else
if [ 条件3 ];then
命令3
elif [ 条件4 ];then
命令4
else
命令5
fi
fi
如果条件1满足,执行命令1;如果条件2也满足执行命令2,如果不满足就只执行命令1结束;
如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5
二、for
https://api.fq.mk/link/qAwcdfqT4zM98MsJ?mu=
1.循环语法结构
- 特点**: 多用于已知次数的循环(**定循环)
- 循环体: do…done之间的内容
循环语法结构,可循环字母或数字
for num in 1 2 3 4 5 字母写法:for sex in a b c d e
do
echo $num
done
可使用通配符写作
for num in {1..5} 字母写法:for sex in {a..e}
类c风格写法
for(( expr1;expr2;expr3 )) # 类C风格的for循环
do
command
done
expr1:定义变量并赋初值
expr2:决定是否进行循环(条件),留空表示一直满足条件(死循环)
expr3:决定循环变量如何改变,决定循环什么时候退出
2.循环控制语句(参数)
参数 | 说明 |
---|---|
continue | 跳过;表示循环体内下面的代码不执行,重新开始下一次循环 |
break | 打断;马上停止循环,执行循环体后面的代码 |
exit | 结束;表示直接结束程序,以下全部不执行 |
3.循环文件
可用命令:
find cat head tail ...
举个栗子:
1,列出目录中文件名单
for file in /etc/*
do
echo $file
done
2,列出目录中所有文件名单
for file in $(find /etc)
do
echo $file
done
4.其他写法示例
# for i in `seq 10`;do echo $i;done
# for i in $(seq 10);do echo $i;done
# for i in `seq 10 -2 1`;do echo $i;done
# for i in {1..10};do echo $i;done
# for i in {0..10..2};do echo $i;done # 大括号中第3个数字2为一步的长度
# for i in {10..1};do echo $i;done
# for i in {10..1..-2};do echo $i;done
# for ((i=1;i<=5;i++));do echo $i;done
# for ((i=1;i<=10;i+=2));do echo $i;done
# for ((i=10;i>=1;i-=2));do echo $i;done
# for i in {a..z}; do echo $i; done
三、while
1.循环语法结构
- 特点:条件为真就进入循环;条件为假就退出循环.多用于不定次数的循环
用for循环与while循环做比较打印1-5
1,while写法
while [ $i -le 5 ]
do
echo $i
let i++
done
----------------------------------------
2,for写法
for ((i=1;i<=5;i++))
do
echo $i
done
----------------------------------------
3,类C写法
while ((i=1;i<=5;i++))
do
echo $i
done
2.死循环
while true 条件永远为true,所以会一直循环下去
do
command
done
其它的死循环写法,会上面一种即可
while :
do
command
done
----------------------------------------
for (( ;1; ))
do
command
done
----------------------------------------
for ((i=1;;i++))
do
command
done
四、until循环(了解)
- 特点:直到满足条件就退出循环
1,until实现
a=1
until [ $a -gt 5 ]
do
echo $a
let a++
done
----------------------------------
2,for实现
a=1
until [ $a -gt 5 ]
do
echo $a
let a++
done
五、随机数实现
- bash默认有一个$RANDOM的变量, 默认范围是0~32767
查看上一次产生的随机数,使用`set |grep RANDOM`
# echo $RANDOM
19862
# set |grep RANDOM
RANDOM=19862
---------------------------------------------
产生0~1之间的随机数
# echo $[$RANDOM%2]
---------------------------------------------
产生0~2之间的随机数
# echo $[$RANDOM%3]
---------------------------------------------
产生1-2之内的随机数
# echo $[$RANDOM%2+1]
---------------------------------------------
产生0-9之内的随机数
# echo $[$RANDOM%10]
---------------------------------------------
产生50-100之内的随机数
# echo $[$RANDOM%51+50]
---------------------------------------------
产生三位数的随机数
# echo $[$RANDOM%900+100]
六、嵌套循环
- 一个循环体内又包含另一个完整的循环
- 在外部循环的每次执行过程中都会触发内部循环,直至内部完成一次循环,才接着执行下一次的外部循环。
- for循环、while循环和until循环可以相互嵌套。
for i in {a..c}
do
for j in {1..3}
do
echo $i$j
done
done
七、case语句
- case语句为多选择语句(多分支结构)
- python里没有case语句,python里用if多分支来实现,数据库的SQL语句里也有case语句。
语法结构
case 变量 in #定义变量
条件1 ) #条件区,用|分割多个条件(相当于or)
command 1 #条件满足时执行的语句
;; #两个分号代表命令结束
条件2 )
command 2
;;
* ) #不满足以上所有模式,执行*)后的语句(相当于else)
command 4 #这里可以不加;;
esac #esac表示case语句结束(类似fi)
case与if 对比
case $sex in
男|man )
echo "帅哥"
;;
女|woman )
echo "美女"
;;
* )
echo "性别有误"
esac
------------------------------------------------
if [ $sex = 男 -o $sex = man ];then
echo "帅哥"
elif [ $sex = 女 -o $sex = woman];then
echo "美女"
else
echo "性别有误"
fi
正则表达式
介绍
正则表达式(Regular Expression、regex或regexp,缩写为RE),也译为正规表示法、常规表示法,是一种字符模式,用于在查找过程中匹配指定的字符。
几乎所有开发语言都支持正则表达式,后面学习的python语言里也有正则表达式.
linux里主要支持正则表达式的命令有grep, sed, awk
正则一,字符位置匹配
表达式 | 说明 | 示例 |
---|---|---|
[] | 括号里的任选单个字符 | [abc][0-9][a-z] |
[^ ] | 不包含:不匹配括号里的任意字符(括号里面的^号为"非",不是开头) | [^abc]表示不为a开头,b开头,c开头 |
1 | 行首,以括号内字符开头 | 2:以a或b或c开头 |
3 | 不以括号里的任意单个字符开头 | 4 不以小写字母开头的 |
^ | 行的开头 | ^root |
$ | 行的结尾 | bash$ |
^$ | 空行 | |
^\t$ | m某行中以\t开头和结尾(\t表示TAB键) | 只有\t的行 |
正则二,字符类型匹配
表达式 | 功能 |
---|---|
[[:alnum:]] | 字母与数字字符 |
[[:alpha:]] | 字母字符(包括大小写字母) |
[[:blank:]] | 空格与制表符 |
[[:digit:]]或[0-9] (常用) | 数字 |
[[:lower:]]或[a-z] (常用) | 小写字母 |
[[:upper:]]或[A-Z] ** (常用**) | 大写字母 |
[[:punct:]] | 标点符号 |
[[:space:]] | 包括换行符,回车等在内的所有空白 |
举很多个栗子:
# grep g. 2.txt
# grep g* 2.txt # 结果比较怪
# grep g.g 2.txt
# grep g*g 2.txt
# grep go.g 2.txt
# grep go.*g 2.txt
# grep -E go{2}g 2.txt
# grep -E 'go{1,2}g' 2.txt # 需要引号引起来,单引双引都可以
# grep -E 'go{1,}g' 2.txt # 需要引号引起来,单引双引都可以
# grep -E go+g 2.txt
# grep -E go?g 2.txt
# ifconfig eth0|grep Bcast| grep -E -o '([0-9]{1,3}.){3}[0-9]{1,3}'
10.1.1.11
10.1.1.255
255.255.255.0
解析:
[0-9]{1,3}\. 代表3个数字接一个.号
([0-9]{1,3}\.){3} 前面用小括号做成一个组,后面{3}代表重重复3次
[0-9]{1,3} 最后一个数字后不需要.号
正则三,字符串长度匹配
名词解释:
元字符: 指那些在正则表达式中具有特殊意义的专用字符,如:点(.) 星(*) 问号(?)等
前导字符:即位于元字符前面的字符 ab**c*** aoo**o.**
注意: 元字符如果想表达字符本身需要转义,如.号就想匹配"."号本身则需要使用\.
字符 | 字符说明 | 示例 |
---|---|---|
* | 前导字符出现0次或者连续多次 | ab* abbbb |
. | 除了换行符以外,任意单个字符 | ab. ab8 abu |
.* | 任意长度的字符 | ab.* abdfdfdf |
{n} | 前导字符连续出现n次 (需要配合grep -E或egrep使用) | [0-9]{3} |
{n,} | 前导字符至少出现n次 (需要配合grep -E或egrep使用) | [a-z]{4,} |
{n,m} | 前导字符连续出现n到m次 (需要配合grep -E或egrep使用) | o{2,4} |
+ | 前导字符出现1次或者多次 (需要配合grep -E或egrep使用) | [0-9]+ |
? | 前导字符出现0次或者1次 (需要配合grep -E或egrep使用) | go? |
( ) | 组字符,多个正则字符组合成一个组来一起调用 | ([0-9]{1,3}.){3} |
perl内置正则(拓展)
Perl内置正则(需要使用grep -P来匹配),这种匹配方式在python也有。但不建议都记住,上面所学的就完全够用了.
\d 匹配数字 [0-9]
\w 匹配字母数字下划线[a-zA-Z0-9_]
\s 匹配空格、制表符、换页符[\t\r\n]
九、sed(编辑器)
sed介绍
- 首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。
- sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。当然你也可以选择修改源文件,需要
sed -i 操作的文件
- 常见的功能有:
- 删除行
- 打印行
- 增加行
- 替换(修改)
sed参数
sed参数
-e 进行多项编辑,即对输入行应用多条sed命令时使用
-n 取消默认的输出
-r 使用扩展正则表达式
-i inplace,原地编辑(修改源文件)
sed操作
d 删除行
p 打印行
a 后面加行
i 前面加行
s 替换修改
1<删除行操作
- d(delete)代表删除
- 执行时,修改的内容不会刷新行号顺序
1>使用行数匹配行
1-删除指定第2行
用管道配合其他命令使用
# head -5 /etc/passwd |cat -n |sed 2d
作为命令单独使用
#sed 2d /etc/passwd
变量引用需要双引号
a=2
# head -5 /etc/passwd |cat -n |sed "$a"d
2-删除第2行到第3行,中间的逗号表示范围
#sed 2,3d /etc/passwd
3-删除第1行和第5行,中间为分号,表示单独的操作
错误,需要引号引起来
#sed 1d;5d /etc/passwd
正确
#sed '1d;5d' /etc/passwd
4-删除第1,2,4行, -e参数是把不同的多种操作可以衔接起来
#sed -e '2d;4d' -e '1d' /etc/passwd
2>使用正则+关键字匹配行
- 任意正则表达式都可以匹配
- 注意: -i参数会直接操作源文件,所以请先不加-i测试,测试OK后再加-i参数
1-删除匹配关键字的行
# head -n 5 /etc/passwd |cat -n |sed '/oo/d'
# sed '/oo/d' /etc/passwd
2-删除以关键字开头的行
# head -n 5 /etc/passwd |sed '/^root/d'
3-删除以关键字结尾的行
# head -n 5 /etc/passwd |sed '/bash$/d'
3<打印行操作
打印行p(print)代表打印,通常配合-n使用
1>使用行数匹配行
1-打印第1行
# head -3 /etc/passwd |cat -n | sed 1p
1 root:x:0:0:root:/root:/bin/bash # 会在原来5行的基础上再打印第1行
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
正确做法
# head -5 /etc/passwd |cat -n | sed -n 1p # 正确做法加一个-n参数
1 root:x:0:0:root:/root:/bin/bash
2-打印第1行和第4行
# head -5 /etc/passwd |sed -ne '1p;4p'
3-打印1-4行
# head -5 /etc/passwd |sed -ne '1,4p'
2>使用正则+关键字匹配行
1-打印有关键字的行
# head -5 /etc/passwd |sed -n '/root/p'
2-打印以关键字开头的行
# head -5 /etc/passwd |sed -n '/^root/p'
3-找出有关键字的行-sed,grep,awk对比
方法1:
# sed -n '/Accepted/p' /var/log/secure
方法2:
# grep Accepted /var/log/secure
方法3:(awk还没学,先了解一下)
# awk '$0~"Accepted" {print $0}' /var/log/secure
4<增加行操作
- a(append)代表后面加行
- i(insert)代表前面插入行
- 执行时,修改的内容不会刷新行号顺序
1>用行号匹配
1-在第2行后加上33333这一行
# sed -i '2a33333' 1.txt
# cat 1.txt
11111
22222
33333
44444
55555
2-在第1行前插入00000这一行
# sed -i '1i00000' 1.txt
# cat 1.txt
00000
11111
22222
33333
44444
55555
2>用正则匹配行
1-在4开头的行的后一行加上ccccc这一行
# sed -i '/^4/accccc' 1.txt
# cat 1.txt
00000
11111
22222
33333
44444
ccccc
55555
5<修改替换操作
- sed的修改替换格式与vi里的修改替换格式一样
- 执行时,修改的内容会刷新列顺序
替换操作语法格式
#sed [选项] '/行关键词/s/被替换部分/新内容部分/关键词列数' 文件路径
1>使用数字匹配行
1-替换每行里指定的匹配字符
参数:s
将/etc/passwd中每行中的第一个关键字:替换为===
# head -5 /etc/passwd |sed 's/:/===/'
root===x:0:0:root:/root:/bin/bash
bin===x:1:1:bin:/bin:/sbin/nologin
daemon===x:2:2:daemon:/sbin:/sbin/nologin
adm===x:3:4:adm:/var/adm:/sbin/nologin
lp===x:4:7:lp:/var/spool/lpd:/sbin/nologin
将/etc/passwd中每行中的第2个关键字:替换为===
# head -5 /etc/passwd |sed 's/:/===/2'
root:x===0:0:root:/root:/bin/bash
bin:x===1:1:bin:/bin:/sbin/nologin
daemon:x===:2:2:daemon:/sbin:/sbin/nologin
adm:X===:3:4:adm:/var/adm:/sbin/nologin
lp:x===:4:7:lp:/var/spool/lpd:/sbin/nologin
2-全部替换
参数:g
将/etc/passwd中每行中的关键字:全部替换为===
# head -5 /etc/passwd |sed 's/:/===/g'
root===x===0===0===root===/root===/bin/bash
bin===x===1===1===bin===/bin===/sbin/nologin
daemon===x===2===2===daemon===/sbin===/sbin/nologin
adm===x===3===4===adm===/var/adm===/sbin/nologin
lp===x===4===7===lp===/var/spool/lpd===/sbin/nologin
3-替换2至4行
将/etc/passwd中2至4行中的关键字:全部替换为===
# head -5 /etc/passwd |sed '2,4s/:/===/g'
root:x:0:0:root:/root:/bin/bash
bin===x===1===1===bin===/bin===/sbin/nologin
daemon===x===2===2===daemon===/sbin===/sbin/nologin
adm===x===3===4===adm===/var/adm===/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
4-替换2行和4行
将/etc/passwd中2和4行中的关键字:全部替换为===
# head -5 /etc/passwd |sed '2s/:/===/g;4s/:/===/g'
root:x:0:0:root:/root:/bin/bash
bin===x===1===1===bin===/bin===/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm===x===3===4===adm===/var/adm===/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
5-替换第2行的第1个和第3个匹配字符
注意后面的数字是2,前面替换了1个,剩下的里面替换第2个也就是原来的第3个
# head -5 /etc/passwd |sed '2s/:/===/;2s/:/===/2'
root:x:0:0:root:/root:/bin/bash
bin===x:1===1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
2>使用正则匹配行
正则关键词需要用//包起来
1.
--------------------------------------------------------------------
以daemon开头的那一行中,关键字:全部替换为===
# head -5 /etc/passwd |sed '/^daemon/s/:/===/g'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon===x===2===2===daemon===/sbin===/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
2.
---------------------------------------------------------------------
以SELINUX开头的行中,将以=开头的部分,替换为=disabled
sed -i '/^SELINUX=/s/=.*/=disabled/' /etc/selinux/config
3>&符号在sed替换里代表前面被替换的字符
理解下面两句的不同:
s/[0-9]/ &/
s/[0-9]/ [0-9]/
6< sed分域操作(拓展)
将()之间的字符串(一般为正则表达式)定义为组,并且将匹配这个表达式的内容保存到一个区域(一个正则表达式最多可以保存9个),它们使用\1到\9来表示。然后进行替换操作
注意: sed分域操作的格式就是替换修改.
1<同一行内,字符顺序变换
格式:
# sed [选项] 's/关键字分组匹配/重新排列后的顺序/' 路径
------------------------------------------------------------------------
示例:** 把`hello,world.sed`变成`world,sed.hello`(注意: 1个逗号1个点号)
方法1:
# echo "hello,world.sed" | sed 's/\(.*\),\(.*\)\.\(.*\)/\2,\3.\1/'
world,sed.hello
此方法\符太多了,建议参考方法2,使用-r扩展模式,就不用加\转义括号了
方法2:
# echo "hello,world.sed" | sed -r 's/(.*),(.*)\.(.*)/\2,\3.\1/'
world,sed.hello
方法3:
# echo "hello,world.sed" | sed -r 's/(.....)(.)(.....)(.)(...)/\3\2\5\4\1/'
world,sed.hello
方法4:
# echo "hello,world.sed" | sed -r 's/(.{5})(.)(.{5})(.)(.{3})/\3\2\5\4\1/'
world,sed.hello
7<多种命令实现方法对比
示例: 以/etc/passwd文件前5行为例,进行如下处理
1>删除每行的第一个字符
# head -5 /etc/passwd |cut -c2-
# head -5 /etc/passwd |sed -r 's/(.)(.*)/\2/'
# head -5 /etc/passwd |sed -r 's/.//1'
# head -5 /etc/passwd |sed -r 's/^.//'
2>删除每行的第九个字符
# head -5 /etc/passwd |cut -c1-8,10-
# head -5 /etc/passwd |sed -r 's/(.{8})(.)(.*)/\1\3/'
# head -5 /etc/passwd |sed -r 's/.//9'
3>删除倒数第5个字符
# head -5 /etc/passwd |rev |cut -c1-4,6- |rev
# head -5 /etc/passwd |sed -r 's/(.*)(.)(....)/\1\3/'
4>把每行的第5个字符和第8个字符互换,并删除第10个字符(新顺序中不加入即是删除)
# head -5 /etc/passwd | sed -r 's/(....)(.)(..)(.)(.)(.)(.*)/\1\4\3\2\5\7/'