命令的类型:
1.内部命令
常驻于内存
[root@shell ~]# man .
这里的 点 “.” 也是一个命令,表示重新加载,等同于source 。
2.外部命令
内部命令是在内核中的,在安装操作系统和shell中的,开机时直接加载在内存中,外部命令是安装在硬盘上的,还要向硬盘和内存进行转换。
所以在进行编写shell时尽量使用内部命令,不要写臃肿命令。
3.别名
查看命令的别名列表
[root@shell ~]# alias
4.hash
查看命令的hash列表
[root@shell ~]# hash
Hash,只对外部命令生效,加载到内存中的hash表中,下次再使用时效率较高。
5.函数
先定义
后调用
6.关键字
if case while for …
对于文本文件的处理,主要用下面几个方法。
grep egrep fgrep:
sed:
正则表达式:
grep 全家桶和sed 后面跟的都是正则表达式。
grep的语法:
grep “正则表达式” 文件名
grep:用于查询文件中符合正则表达式的内容
正则表达式是一组有特殊含义的字符串,用这个来代表一类内容。
正则表达式的字符分为元字符和普通字符。
普通字符:大小写字母和数字。
元字符:有特殊含义的字符。
测试文件:
[root@www shell]# cat test-file1.txt //文件内容。
root
rooot
roooooot
rt
at
cat
caaaat
/s
/help
/fuck
dog/
pi/g
nam\e
AAAA
BBB
DDDDDD
AABB
1、^ 行首定位符
[root@www shell]# grep "^A" test-file1.txt //在行首是A的行
AAAA
AABB
在这里其实"^A"就是一个正则表达式了。
2、$ 行尾定位符
[root@www shell]# grep "B$" test-file1.txt //行尾是B的
BBB
AABB
3、. 单个任意字符
[root@www shell]# grep "r.t" test-file1.txt //查询有r和t 之间有1个字符的项,没有结果
[root@www shell]# grep "r..t" test-file1.txt //查询r和t之间有2个字符的项,有一个root。并输出来。
root
4、* 前面的字符可以是任意个(0~无穷大)
[root@www shell]# grep "r*t" test-file1.txt //这个并不是查询r和t之间有无数个字符的,而是查询t前面有n个r的项,n取0-无穷大。
root //这个是t前边有0个r
rooot //t前边有0个r
roooooot
rt //t前边有1个r
at //t前边有0个r
cat
caaaat
[root@www shell]# grep "ro*t" test-file1.txt //这个表示的是r和t之间有n个o,n取0-无穷大
root //2个o
rooot //3个o
roooooot //6个o
rt //0个o
5、[] 匹配指定字符组中的任意1个字符
[A-Z]
[a-z]
[a-Z] 所有的字母
[0-9]
[a-Z0-9] 字母+数字
[^a-Z0-9] ^取反,不是字母+数字==符号
栗子:
[root@www shell]# grep "^[a-c]" test-file1.txt //以abc小写,开头的行。
at
cat
caaaat
6、 \ ( \ ) 、
标签,保存被匹配的字符
标签在一个表达式中,最多出现9个
从左向右,依次排序,第一个标签,\ 1 ;第二个 \ 2
[root@www shell]# grep "\(.\)\1\1" test-file1.txt // 前边的\(.\)是查询任意字符,\1表示第一个位置(也就是与第一个任意字符相同)
#//所以这行命令的意思就是3个相同的字符连续出现的项。
rooot //ooo 三个相连 符合所以搜出了
roooooot //这个o正好是6个,所以符合2个3连,能被搜出。
caaaat //包含三连的
AAAA
BBB
DDDDDD
7、\ { \ }
\ { m \ } 前面的字符有m个
\ { m , \ } 前面的字符>=m个
\ { m , n \ } 前面的字符>=m且 <=n 个
[root@www shell]# grep "B\{3\}" test-file1.txt //三个A相连的
BBB
[root@www shell]# grep "A\{3\}" test-file1.txt
AAAA
8、\ <\ >
\ < 词首定位符
\ > 词尾定位符
词:单词 一串连续的字母、数字,每个词之间用符号分割,任意符号都可以。这个词可能不是一个“词” ,在这里,aaa可能就是一个词,lll可能是一个词。
[root@www shell]# grep "\<pi\>" test-file1.txt
pi/g
pi后边有个字符,于是pi就被识别成一个词,能被搜索出来。
9、\ 转义。
这个字符后边跟的符号只是符号不代表别的意思。这个点就是单纯的点。
[root@www shell]# grep "\." test-file1.txt
d.og
但是注意一点,在正则里单引号和双引号没有区别,在shell中有区别。
””双引号不能屏蔽 \ 反斜杠 ` 反引号 $ 符号。遇到这几个不能识别成字符,直接识别成所含意思,哪怕转义也不行。单引号则可以强制识别成字符。
如下边的栗子:
[root@www shell]# grep "\$" test-file1.txt
root
rooot
roooooot
rt
at
cat
caaaat
/s
/help
/fuck
dog/
pi/g
nam\e
AAAA
BBB
DDDDDD
AABB
too$
d.og
[root@www shell]# grep '\$' test-file1.txt
too$
双引号里有 \ 转义了,但是依旧不能用,单引号里转义可以用。
拓展的正则元字符:
这个要跟在egrep后用。
| 或
+ 前面的字符匹配>=1次(1~无穷大)
? 前面的字符配置0次或1次
() == \(\)
{m} == \{m\}
{m,} == \{m,\}
{m,n} == \{m,n\}
[root@www shell]# cat test-file2.txt
abc
123
aaa
dfe
qwre
aaad
gggjuyhk
eswfsaaa
###
@$^#^
Q@W#E%R
adb dev ops
name is cat
上边是文件的内容。
栗子:
1、| 或。满足 a开头或者e开头的救会被搜索出来
[root@www shell]# egrep '^a|^e' test-file2.txt
abc
aaa
aaad
eswfsaaa
adb dev ops
2、+ 表示+前的字母有1到正无穷个。
?表示?前的字符有0 或1 个。
//例子中表示d前边有1到正无穷个a 的项会被搜索出来。
[root@www shell]# egrep 'a+d' test-file2.txt
aaad
adb dev ops
//这里表示d前边有1个或者有0个a 的会被搜索出来。aaad也满足条件。
[root@www shell]# egrep 'a?d' test-file2.txt
dfe
aaad
adb dev ops
3、()
[root@www shell]# egrep '(a)\1\1' test-file2.txt
aaa
aaad
eswfsaaa
这个等同于有 \ 的那个。
4、{m}
[root@www shell]# egrep 'g{3}' test-file2.txt
gggjuyhk
这些都等价于有\ 的那个。
fgrep
取消字符的特殊含义。
[root@www shell]# fgrep '^#' test-file2.txt
@$^#^
//在这里,^这东西已经失去了意义,只是符号。
sed: sed也叫流编辑器,可以过滤和转换。
工作原理:
以行为单位处理文件,将一行流入模式空间进行操作,命令和选项将行操作完成后,输出到标准输出(控制台)。然后处理下一行。
sed默认会处理所有的行,哪怕不做操作,也会将全部的行都“流”一遍。
sed的语法格式:
sed [选项] ‘/定址/命令‘ 文件名
sed只有在语法格式出错是$?才会非0 ,剩下的情况都为0.
grep则是搜索不出来就为非0
sed的选项和命令:
选项:
-n 关闭模式空间的输出
-e 多点编辑
-i 就地修改,直接编辑源文件
-f 指定sed脚本的名字
-r 支持拓正则
命令:
d 删除匹配行
p 打印匹配行
q 退出模式空间
s 替换,用一个字符替换另一个
y 将字符转换为另一字符(不支持正则表达式)
r 从文件中读
w 另存为
a 在匹配行下一行添加一行或多行
i 在匹配行上一行添加一行或多行
c 本行替换
h H 将内容从模式空间弄到保留空间,h是重定向(覆盖),H是追加
g G 讲内容从保留空间弄到模式空间,g是重定向(覆盖),G是追加
测试用文件如下:
[root@www shell]# cat test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
[root@www shell]#
直接写命令,不加 - i 选项的话并不会直接修改源文件,只是在模式空间修改,然后输出。
d 删除含有匹配项的行
[root@www shell]# sed '1,3d' test-file3.txt
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
//1,3 删除第一至第三行 只写1 表示删除第1行。
**e是多点编辑,**可以这样使用,删除1和3行。
[root@www shell]# sed -e '1d' -e '3d' test-file3.txt
user2:x:2031:2031::/home/user2:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
p 打印输出 ,在模式空间中操作打印一行,再将模式空间中有的哪一行输出,所以是1-3行是2行。
[root@www shell]# sed '1,3p' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
这个一般和-n一起使用:
这样模式空间的那一堆就不输出了,只输出 p 操作的,那几行。
[root@www shell]# sed -n '1,3p' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
q 退出模式空间。
正常来说sed一行进入模式空间,然后输出,是必经的,会读取和操作所有行。 但是q ,会让在sed到指定行退出,也就不读取下边的行了。
[root@www shell]# sed 'q' test-file3.txt //这个怎么都会都去一遍,第一行。
user1:x:2030:2030::/home/user1:/bin/bash
[root@www shell]# sed '1q' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
[root@www shell]# sed '2q' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
s:替换。
s的语法如下:
sed ‘s/模式匹配/替换内容/旗标’ 文件名
模式匹配:可以是正则表达式,也可以是普通的字符,当然普通的字符也可以算作正则表达式,只不过范围比较小。
替换内容:字符串,将模式匹配替换成什么。这个不能使正则。
旗标:主要用的有下边几种
n:1-512之间的正整数,表示第n次出现的匹配内容
g:全局替换
p:打印替换的行
w:另存为
i :不区分大小写
默认匹配第一个替换。
[root@www shell]# sed 's/u/U/' test-file3.txt
User1:x:2030:2030::/home/user1:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash
User3:x:2032:2032::/home/user3:/bin/bash
User4:x:2033:2033::/home/user4:/bin/bash
....省略 不复制了。。。
n=2 , 替换每行第二个匹配的。
[root@www shell]# sed 's/u/U/2' test-file3.txt
user1:x:2030:2030::/home/User1:/bin/bash
user2:x:2031:2031::/home/User2:/bin/bash
user3:x:2032:2032::/home/User3:/bin/bash
user4:x:2033:2033::/home/User4:/bin/bash
g,替换全局的
[root@www shell]# sed 's/u/U/g' test-file3.txt
User1:x:2030:2030::/home/User1:/bin/bash
User2:x:2031:2031::/home/User2:/bin/bash
User3:x:2032:2032::/home/User3:/bin/bash
p 打印,嗯输出2行了
[root@www shell]# sed 's/u/U/p' test-file3.txt
User1:x:2030:2030::/home/user1:/bin/bash
User1:x:2030:2030::/home/user1:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash
w另存为,可以制定一个文件,然后就不在控制台输出了。
[root@www shell]# sed -n 's/u/U/w wwww.txt' test-file3.txt
[root@www shell]# cat wwww.txt
User1:x:2030:2030::/home/user1:/bin/bash
User2:x:2031:2031::/home/user2:/bin/bash
User3:x:2032:2032::/home/user3:/bin/bash
User4:x:2033:2033::/home/user4:/bin/bash
User5:x:2034:2034::/home/user5:/bin/bash
User6:x:2035:2035::/home/user6:/bin/bash
User7:x:2036:2036::/home/user7:/bin/bash
User8:x:2037:2037::/home/user8:/bin/bash
User9:x:2038:2038::/home/user9:/bin/bash
User10:x:2039:2039::/home/user10:/bin/bash
i 不区分大小写的替换。
[root@www shell]# cat test-file1.txt
root
rooot
roooooot
rt
at
cat
caaaat
/s
/help
/fuck
dog/
pi/g
nam\e
AAAA
BBB
DDDDDD
AABB
too$
d.og
[root@www shell]# sed -n 's/a/ii/igp' test-file1.txt
iit
ciit
ciiiiiiiit
niim\e
iiiiiiii
iiiiBB
//这些东西都是可以一起使用的,全局的a和A,都换成ii,并且打印做了改变的行,不显示模式空间的输出。结果就在上边。
y 讲一个字符转换成另一个字符。
[root@www shell]# sed 'y/qwertyuioplkjhgfdsazxcvbnm/QWERTYUIOPLKJHGFDSAZXCVBNM/' test-file3.txt
USER1:X:2030:2030::/HOME/USER1:/BIN/BASH
USER2:X:2031:2031::/HOME/USER2:/BIN/BASH
USER3:X:2032:2032::/HOME/USER3:/BIN/BASH
USER4:X:2033:2033::/HOME/USER4:/BIN/BASH
USER5:X:2034:2034::/HOME/USER5:/BIN/BASH
//把所有的小写字母换成大写。
a 在行下插入内容。
i 在行上插入内容。
[root@www shell]# sed 'a hhaha' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
hhaha
user2:x:2031:2031::/home/user2:/bin/bash
hhaha
user3:x:2032:2032::/home/user3:/bin/bash
hhaha
......后边不复制了。。。。。
//不指定定址的话默认所有嘛。
[root@www shell]# sed '1a hhaha' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
hhaha
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
//只在第一行后边加。
[root@www shell]# sed '1i hhaha' test-file3.txt
hhaha
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
//行前加
[root@www shell]# sed '1i hhaha\njjjjjj' test-file3.txt
hhaha
jjjjjj
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
//可以加多行的,\n是换行。
w 另存为,前边可以加行数
[root@www shell]# sed '3w test-www.txt' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
..后边省略,这个是从模式空间输出的。-n 可以没有
[root@www shell]# cat test-www.txt
user3:x:2032:2032::/home/user3:/bin/bash
r读取文件,行数与后边的文件行数相同。
[root@www shell]# sed -n 'r test-www.txt' test-file3.txt
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
hH
gG
这个东西会启动一个叫保留空间的东西。
处理文本文件–模式空间(PATT)
可以用来存储文件内容(行)–保留空间(HOLD),保留空间,默认有一个空行
如果有hHgG命令就会将文件的行写到保留空间中,在输出模式空间的东西,如果只有h 将模式空间弄到保留空间,没有意义,有去有回才有用。
[root@www shell]# sed '1h;4g' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user1:x:2030:2030::/home/user1:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
上边命令的执行过程:
sed读取第一行,将第一行复制到模式空间,因为是h所以会覆盖那个空行,现在保留空间有一行,也就是文件的第一行。在sed读取第二行是,没有操作。
在sed读取第4行时,有g命令,将保留空间的内容覆盖回模式空间,也就是将保留空间的内容,覆盖到模式空间的第4行,保留空间的内容时文件的第一行,最后的结果就是第一行覆盖第4行。
下边都没有命令,也就没有操作。
最终输出模式空间的内容,显示结果,第4行没有了取而代之的是第1行。
[root@www shell]# sed '1h;4G' test-file3.txt
user1:x:2030:2030::/home/user1:/bin/bash
user2:x:2031:2031::/home/user2:/bin/bash
user3:x:2032:2032::/home/user3:/bin/bash
user4:x:2033:2033::/home/user4:/bin/bash
user1:x:2030:2030::/home/user1:/bin/bash
user5:x:2034:2034::/home/user5:/bin/bash
user6:x:2035:2035::/home/user6:/bin/bash
user7:x:2036:2036::/home/user7:/bin/bash
user8:x:2037:2037::/home/user8:/bin/bash
user9:x:2038:2038::/home/user9:/bin/bash
user10:x:2039:2039::/home/user10:/bin/bash
H、G是追加,不会删除原来行,执行过程同上,所以会出现两行。第4行没有被覆盖,后边还多了个第1行。
-i 加后缀名
[root@www 1111shell]# sed -i.hhh 's/cat/CAT/g' pet
[root@www 1111shell]# cat pet
dog CAT bird fish
CAT dog fish bird
CAT CAT apple banana
hotdog fuck name sex
[root@www 1111shell]# cat pet.hhh
dog cat bird fish
cat dog fish bird
cat cat apple banana
hotdog fuck name sex
-i 后边的后缀名随便写,就是备份用,会直接修改文件,但是也会备份源文件,源文件不做修改,后缀名就是新的后缀名。
和下边这个正好相反,下边的是修改新文件,源文件不动。
[root@www 1111shell]# sed 's/cat/CAT/g' pet.hhh > pet.txt
本文深入解析了Shell中的命令类型,包括内部命令、外部命令、别名、hash、函数和关键字的使用。详细介绍了文本处理工具grep、sed的工作原理及正则表达式的应用,通过实例展示了如何高效地使用这些工具进行文本搜索和编辑。
746

被折叠的 条评论
为什么被折叠?



