文本三剑客

2023-03-14 16:08:50 浏览数 (3)

通配符

通配符是shell在做PathnameExpansion时用到的。说白了一般只用于文件名匹配,它是由shell解析 的,比如 find,ls,cp,mv等 shell常见通配符

代码语言:javascript复制
*:匹配0或多个字符
?:匹配任意一个字符
[list]:匹配list中任意单个字符
[c1‐c2]:匹配c1‐c2中任意单个字符
[^c1‐c2]/[!c1‐c2]:不匹配c1‐c2中任意字符
{string1,string2,...}:匹配{}中任意单个字符串
  • shell 元字符
代码语言:javascript复制
IFS://
CR:
=:设定变量
$:取变量值
>/< :重定向
|:管道
&:后台执行命令
():在子shell中执行命令/运算或命令替换
{}:函数中执行/变量替换的界定范围
;:命令结束后,忽略其返回值,继续执行下一个命令
&&:命令结束后,若为true,继续执行下一个命令
||:命令结束后,若为false,继续执行下一个命令
!:非
#:注释
:转义符
  • shell转义符
代码语言:javascript复制
'':硬转义,内部所有shell元字符,通配符都会被关掉
"":软转义,内部

find文件查找

  • 实时查找工具,通过遍历指定路径下的文件系统完成文件查找
  • 工作特点
    • 查找速度略慢
    • 精确查找
    • 实时查找
    • 可以满足多种条件匹配
代码语言:javascript复制
find [选项] [路径] [查找条件   处理动作]
查找路径:指定具体目录路径,默认是当前文件夹
查找条件:指定的查找标准(文件名/大小/类型/权限等),默认是找出所有文件
处理动作:对符合条件的文件做什么操作,默认输出屏幕

查找条件

  • 查找条件
代码语言:javascript复制
根据文件名查找:
    ‐name "filename" 支持global
    ‐iname "filename" 忽略大小写
    ‐regex "PATTERN" 以Pattern匹配整个文件路径字符串,而不仅仅是文件名称
根据属主和属组查找:
    ‐user USERNAME:查找属主为指定用户的文件
    ‐group GROUPNAME:查找属组为指定属组的文件
    ‐uid UserID:查找属主为指定的ID号的文件
    ‐gid GroupID:查找属组为指定的GID号的文件
    ‐nouser:查找没有属主的文件
    ‐nogroup:查找没有属组的文件
根据文件类型查找:
    ‐type Type:
    f/d/l/s/b/c/p
根据文件大小来查找:
    ‐size [ |‐]N[bcwkMG]
根据时间戳:
    天:
        ‐atime [ |‐]N
        ‐mtime
        ‐ctime
    分钟:
        ‐amin N
        ‐cmin N
        ‐mmin N
根据权限查找:
    ‐perm [ |‐]MODE
    MODE:精确权限匹配
    /MODE:任何一类(u,g,o)对象的权限中只要能一位匹配即可
    ‐MODE:每一类对象都必须同时拥有为其指定的权限标准
组合条件:
    与:‐a
    或:‐o
    非:‐not
相关案例:找出/tmp目录下,属主不是root,且文件名不是fstab的文件:
find /tmp ( -not -user root -a -not -name fstab ) -ls
  • 根据文件名查找
代码语言:javascript复制
[root@localhost ~]# find /etc -name "ifcfg-ens33"
[root@localhost ~]# find /etc -iname "ifcfg-ens33" # 忽略大小写
[root@localhost ~]# find /etc -iname "ifcfg*"
  • 按文件大小
代码语言:javascript复制
[root@localhost ~]# find /etc -size  5M # 大于5M
[root@localhost ~]# find /etc -size 5M # 等于5M
[root@localhost ~]# find /etc -size -5M # 小于5M
[root@localhost ~]# find /etc -size  5M -ls # 找到的处理动作-ls
  • 指定查找的目录深度
代码语言:javascript复制
[root@localhost ~]# find / -maxdepth 3 -a -name "ifcfg-ens33" # 最大查找深度
# -a是同时满足,-o是或
[root@localhost ~]# find / -mindepth 3 -a -name "ifcfg-ens33" # 最小查找深度
  • 按时间找
代码语言:javascript复制
[root@localhost ~]# find /etc -mtime  5 # 修改时间超过5天
[root@localhost ~]# find /etc -mtime 5 # 修改时间等于5天
[root@localhost ~]# find /etc -mtime -5 # 修改时间5天以内
  • 按照文件属主、属组找
代码语言:javascript复制
[root@localhost ~]# find /home -user xwz # 属主是xwz的文件
[root@localhost ~]# find /home -group xwz
[root@localhost ~]# find /home -user xwz -group xwz
[root@localhost ~]# find /home -user xwz -a -group root
[root@localhost ~]# find /home -user xwz -o -group root
[root@localhost ~]# find /home -nouser # 没有属主的文件
[root@localhost ~]# find /home -nogroup # 没有属组的文件
  • 按文件类型
代码语言:javascript复制
[root@localhost ~]# find /dev -type d
  • 按文件权限
代码语言:javascript复制
[root@localhost ~]# find / -perm 644 -ls
[root@localhost ~]# find / -perm -644 -ls # 权限小于644的
[root@localhost ~]# find / -perm 4000 -ls
[root@localhost ~]# find / -perm -4000 -ls
  • 按正则表达式
代码语言:javascript复制
[root@localhost ~]# find /etc -regex '.*ifcfg-ens[0-9][0-9]'
# .* 任意多个字符
# [0-9] 任意一个数字
  • 条件组合
代码语言:javascript复制
-a:多个条件and并列
-o:多个条件or并列
-not:条件取反

处理动作

代码语言:javascript复制
‐print:默认的处理动作,显示至屏幕
‐ls:类型于对查找到的文件执行“ls ‐l”命令
‐delete:删除查找到的文件
‐fls /path/to/somefile:查找到的所有文件的长格式信息保存至指定文件中
‐ok COMMAND {}:对查找到的每个文件执行由COMMAND指定的命令
对于每个文件执行命令之前,都会交换式要求用户确认
‐exec COMMAND {} :对查找到的每个文件执行由COMMAND指定的命令
[root@server1 ~]# find /etc/init.d/ -perm -111 -exec cp -r {} dir1/ ;
{}:用于引用查找到的文件名称自身
注意:find传递查找到的文件至后面指定的命令时,查找到所有符合条件的文件一次性传递给后面的命
令;另一种方式可规避此问题
find | xargs COMMAND

正则表达式

正则表达式是用来匹配字符串的,针对文件内容的文本过滤工具里,大都用到正则表达式,如vi, grep,awk, sed等

代码语言:javascript复制
##字符匹配
    .:匹配任意单个字符
    []:匹配指定范围内任意单个字符 [a-z] [0-9]
    [^]:匹配指定范围外任意单个字符 [^a-z] [^0-9]
    [:alnum:]:字母与数字字符
    [:alpha:]:字母
    [:ascii:]:ASCII字符
    [:blank:]:空格或制表符
    [:cntrl:]:ASCII控制字符
    [:digit:]:数字
    [:graph:]:非控制、非空格字符
    [:lower:]:小写字母
    [:print:]:可打印字符
    [:punct:]:标点符号字符
    [:space:]:空白字符,包括垂直制表符
    [:upper:]:大写字母
    [:xdigit:]:十六进制数字
##匹配次数
    *:匹配前面的字符任意次数
    .*:匹配任意长度的字符
    ?:匹配其前面字符0或1次,即前面的可有可无 'a?b'
     :匹配其前面的字符至少1次 'a b'
    {m}:匹配前面的字符m次
    {m,n}:匹配前面的字符至少m次,至多n次
    {0,n}:匹配前面的字符至多n次
    {m,}:匹配前面的字符至少m次
    ##位置锚定
    ^:行首锚定,用于模式的最左侧
    $:行末锚定,用于模式的最右侧
    ^PATTERN$:用于模式匹配整行;
    ^$:空行
    < 或 b:词首锚定,用于单词模式的左侧
    > 或 b:词尾锚定,用于单词模式的右侧
    :匹配整个单词 ''
##分组
    ():将一个或多个字符捆绑在一起;当作一个字符
    (xy)*ab
    Note:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命令
方式为:
    1,2,3……
    1:从左侧起,第一个左括号以及与之匹配右括号之间的模式所匹配到的字符;
    (ab (xy)*):
    1:ab (xy)*
    2:xy
  • 扩展正则表达式
代码语言:javascript复制
##字符匹配
.
[]
[^]
##次数匹配
*
?:0次或1次
 :1次或多次
{m}:匹配m次
{m,n}:至少m次,至多n次
##位置锚定
##分组
()
##或者
a|b
C | cat :C或cat
(C|c)at : C或c

Linux三剑客之grep

grep作用:过滤文本内容

选项

描述

-E :--extended--regexp

模式是扩展正则表达式(ERE)

-i :--ignore--case

忽略大小写

-n: --line--number

打印行号

-o:--only--matching

只打印匹配的内容

-c:--count

只打印每个文件匹配的行数

-B:--before--context=NUM

打印匹配的前几行

-A:--after--context=NUM

打印匹配的后几行

-C:--context=NUM

打印匹配的前后几行

--color[=WHEN]

匹配的字体颜色,别名已定义了

-v:--invert--match

打印不匹配的行

-e

多点操作eg:grep -e "^s" -e "s$"

样本文件内容

代码语言:javascript复制
[root@localhost ~]# cat test
asdkahsduoa
aslkdsl
oiofr
sdjo
A
F
aSDD
CASDC

asdo
ca

实例

实例1:打印出所有的a无论大小写 : -i选项

代码语言:javascript复制
[root@localhost ~]# grep -i "a" test
asdkahsduoa
aslkdsl
A
aSDD
CASDC
asdo
ca

实例2:打印出所有的a无论大小写,并且显示该字符串所在的行 : -n选项

代码语言:javascript复制
[root@localhost ~]# grep -in "a" test
1:asdkahsduoa
2:aslkdsl
5:A
7:aSDD
8:CASDC
10:asdo
11:ca

实例3:仅仅打印出所有匹配的字符串: -o选项

代码语言:javascript复制
[root@localhost ~]# grep -io "a" test
a
a
a
a
A
a
A
a
a

实例4:打印出匹配的字符串有多少行 -c选项

代码语言:javascript复制
[root@localhost ~]# grep -ic "a" test
7

实例5:打印出字符S前面的2行 -B

代码语言:javascript复制
[root@localhost ~]# grep -B 2 "S" test
A
F
aSDD
CASDC

实例6:打印出字符S后面的2行 -A

代码语言:javascript复制
[root@localhost ~]# grep -A 2 "S" test
aSDD
CASDC

asdo

实例7:打印出字符S前后2行 -C

代码语言:javascript复制
[root@localhost ~]# grep -C 2 "S" test
A
F
aSDD
CASDC

asdo

实例8:打印出不包含大小s的所有行 取反 -v

代码语言:javascript复制
[root@localhost ~]# grep -iv "S" test
oiofr
A
F

ca

grep可以从文件当中直接搜索某个关键词,也可以从标准输入里面搜索

代码语言:javascript复制
[root@localhost ~]# grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@localhost ~]# cat /etc/passwd | grep "root"
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

正则表达式(基于grep)

  • 功能就是用来检索、替换那些符合某个模式(规则)的文本,正则表达式在每种语言中都会有;
  • 正则表达式就是为了处理大量的文本或字符串而定义的一套规则和方法
  • 通过定义的这些特殊符号的辅助,系统管理员就可以快速过滤,替换或输出需要的字符串
  • Linux正则表达式一般以行为单位处理

基础正则表达式

符号

描述

.

匹配任意单个字符(必须存在)

^

匹配以某个字符开头的行

$

配以什么字符结尾的行

*

匹配前面的一个字符出现0次或者多次;eg:a*b

.*

表示任意长度的任意字符

[]

表示匹配括号内的一个字符

[^]

匹配[^字符]之外的任意一个字符

[]

匹配非[^字符]内字符开头的行

<

锚定 单词首部;eg:

>

锚定 单词尾部:eg:root>

{m,n}

表示匹配前面的字符出现至少m次,至多n次

()

表示对某个单词进行分组;1表示第一个分组进行调用

扩展正则

  • egrep ...
  • grep -E ...
  • 扩展正则支持所有基础正则;
  • 并有补充 扩展正则中{}和[]不用转义可以直接使用;

符号

描述

表示前面的字符至少出现1次的情况

表示“或”

表示前面的字符至多出现1次的情况

最常用

查看配置文件时去除所有的注释和空行

代码语言:javascript复制
[root@localhost ~]# grep -Ev "^#|^$" /etc/ssh/sshd_config

Linux三剑客之sed

Linux sed命令是利用script来处理文本文件。

sed可依照script的指令,来处理、编辑文本文件。

sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

语法

代码语言:javascript复制
sed的命令格式: sed [option] 'sed command' filename
sed的脚本格式:sed [option] ‐f 'sed script' filename
常用选项:
‐n :只打印模式匹配的行
‐e :直接在命令行模式上进行sed动作编辑,此为默认选项
‐f :将sed的动作写在一个文件内,用–f filename 执行filename内的sed动作
‐r :支持扩展表达式
‐i :直接修改文件内容
查询文本的方式
使用行号和行号范围
x:行号
x,y:从x行到y行
x,y!:x行到y行之外
/pattern:查询包含模式的行
/pattern/, /pattern/:查询包含两个模式的行
/pattern/,x:x行内查询包含模式的行
x,/pattern/:x行后查询匹配模式的行

动作说明

代码语言:javascript复制
常用选项:
p:打印匹配的行(‐n)
=:显示文件行号
a:指定行号后添加新文本
i:指定行号前添加新文本
d:删除定位行
c:用新文本替换定位文本
w filename:写文本到一个文件
r filename:从另一个文件读文本
s///:替换
替换标记:
g:行内全局替换
p:显示替换成功的行
w:将替换成功的结果保存至指定文件
q:第一个模式匹配后立即退出
{}:在定位行执行的命令组,用逗号分隔
g:将模式2粘贴到/pattern n/

a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)

c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!

d :删除,因为是删除啊,所以 d 后面通常不接任何东西;

i :插入, i的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);

p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行

s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!

实例

在testfile文件的第四行后添加一行,并将结果输出到标准输出

代码语言:javascript复制
[root@localhost ~]# sed -e 4anewline test
line one
line two
line three
line four
newline
line five

以行为单位的新增/删除

将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '2,5d'
    1 root:x:0:0:root:/root:/bin/bash
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10 operator:x:11:0:operator:/root:/sbin/nologin
    11 games:x:12:100:games:/usr/games:/sbin/nologin
    12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    13 nobody:x:99:99:Nobody:/:/sbin/nologin
    14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    15 dbus:x:81:81:System message bus:/:/sbin/nologin
    16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin

sed 的动作为 '2,5d' ,那个 d 就是删除!因为 2-5 行给他删除了,所以显示的数据就没有 2-5 行罗~ 另 外,注意一下,原本应该是要下达 sed -e 才对,没有 -e 也行啦!同时也要注意的是, sed 后面接的动 作,请务必以 '' 两个单引号括住喔!

只要删除第 2 行

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '2d'
    1 root:x:0:0:root:/root:/bin/bash
    3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10 operator:x:11:0:operator:/root:/sbin/nologin
    11 games:x:12:100:games:/usr/games:/sbin/nologin
    12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    13 nobody:x:99:99:Nobody:/:/sbin/nologin
    14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    15 dbus:x:81:81:System message bus:/:/sbin/nologin
    16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin

要删除第 3 到最后一行

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '3,$d'
    1 root:x:0:0:root:/root:/bin/bash
    2 bin:x:1:1:bin:/bin:/sbin/nologin

在第二行后(亦即是加在第三行)加上『hello world』字样

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '2ahello world'
    1 root:x:0:0:root:/root:/bin/bash
    2 bin:x:1:1:bin:/bin:/sbin/nologin
hello world
    3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10 operator:x:11:0:operator:/root:/sbin/nologin
    11 games:x:12:100:games:/usr/games:/sbin/nologin
    12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    13 nobody:x:99:99:Nobody:/:/sbin/nologin
    14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    15 dbus:x:81:81:System message bus:/:/sbin/nologin
    16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin

加在第二行前面

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '2ihello world'
    1 root:x:0:0:root:/root:/bin/bash
hello world
    2 bin:x:1:1:bin:/bin:/sbin/nologin
    3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10 operator:x:11:0:operator:/root:/sbin/nologin
    11 games:x:12:100:games:/usr/games:/sbin/nologin
    12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    13 nobody:x:99:99:Nobody:/:/sbin/nologin
    14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    15 dbus:x:81:81:System message bus:/:/sbin/nologin
    16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin

增加多行文字

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '2ahello world
> nihao'
    1 root:x:0:0:root:/root:/bin/bash
    2 bin:x:1:1:bin:/bin:/sbin/nologin
hello world
nihao
    3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10 operator:x:11:0:operator:/root:/sbin/nologin
    11 games:x:12:100:games:/usr/games:/sbin/nologin
    12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    13 nobody:x:99:99:Nobody:/:/sbin/nologin
    14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    15 dbus:x:81:81:System message bus:/:/sbin/nologin
    16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin

以行为单位的替换与显示

将第2-5行的内容取代成为『No 2-5 number』

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '2,5cNo 2-5 number'
    1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10 operator:x:11:0:operator:/root:/sbin/nologin
    11 games:x:12:100:games:/usr/games:/sbin/nologin
    12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    13 nobody:x:99:99:Nobody:/:/sbin/nologin
    14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    15 dbus:x:81:81:System message bus:/:/sbin/nologin
    16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin

仅列出 /etc/passwd 文件内的第 5-7 行

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed -n '5,7p'
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

数据的搜寻并显示

搜索 /etc/passwd有root关键字的行

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed -n '/root/p'
    1 root:x:0:0:root:/root:/bin/bash
    10 operator:x:11:0:operator:/root:/sbin/nologin

数据的搜寻并删除

删除/etc/passwd所有包含root的行,其他行输出

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed '/root/d'
    2 bin:x:1:1:bin:/bin:/sbin/nologin
    3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    11 games:x:12:100:games:/usr/games:/sbin/nologin
    12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    13 nobody:x:99:99:Nobody:/:/sbin/nologin
    14 systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
    15 dbus:x:81:81:System message bus:/:/sbin/nologin
    16 polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    17 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    18 postfix:x:89:89::/var/spool/postfix:/sbin/nologin

数据的搜寻并执行命令

搜索/etc/passwd,找到root对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里 把bash替换为blueshell,再输出这行

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed -n '/root/{s/bash/blueshell/p;q}'
    1 root:x:0:0:root:/root:/bin/blueshell

最后的q是退出,不然会继续找下去

数据的搜寻并替换

除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的搜寻并取代

代码语言:javascript复制
sed 's/要被取代的字串/新的字串/g'

查询 IP

原始信息

代码语言:javascript复制
[root@localhost ~]# ifconfig
ens33: flags=4163 mtu 1500
        inet 192.168.91.128 netmask 255.255.255.0 broadcast 192.168.91.255
        inet6 fe80::2de4:b37a:36e9:ae2e prefixlen 64 scopeid 0x20
        ether 00:0c:29:d3:76:83 txqueuelen 1000 (Ethernet)
        RX packets 33461 bytes 32133707 (30.6 MiB)
        RX errors 0 dropped 0 overruns 0 frame 0
        TX packets 11322 bytes 1300148 (1.2 MiB)
        TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73 mtu 65536
        inet 127.0.0.1 netmask 255.0.0.0
        inet6 ::1 prefixlen 128 scopeid 0x10
        loop txqueuelen 1000 (Local Loopback)
        RX packets 10 bytes 697 (697.0 B)
        RX errors 0 dropped 0 overruns 0 frame 0
        TX packets 10 bytes 697 (697.0 B)
        TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

取有IP地址那一行

代码语言:javascript复制
[root@localhost ~]# ifconfig | sed -n '/netmask/p'
    inet 192.168.91.128 netmask 255.255.255.0 broadcast 192.168.91.255
    inet 127.0.0.1 netmask 255.0.0.0

删除IP地址前面和后面的东西

代码语言:javascript复制
[root@localhost ~]# ifconfig | sed -n '/netmask/p' | sed 's/^.*inet //g' |
sed 's/ netmask.*$//g'
192.168.91.128
127.0.0.1

取第一行

代码语言:javascript复制
[root@localhost ~]# ifconfig | sed -n '/netmask/p' | sed 's/^.*inet //g' |
sed 's/ netmask.*$//g' | sed -n '1p'
192.168.91.128

可以在末尾加g替换每一个匹配的关键字,否则只替换每行的第一个

另一种方式:

代码语言:javascript复制
[root@localhost ~]# ip a|sed -n '/inet /p'|sed 's/^.*inet //g'|sed's//.*$//g'|sed -n '2p

多点编辑

一条sed命令,删除/etc/passwd第三行到末尾的数据,并把bash替换为blueshell

代码语言:javascript复制
[root@localhost ~]# nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
    1 root:x:0:0:root:/root:/bin/blueshell
    2 bin:x:1:1:bin:/bin:/sbin/nologin

-e表示多点编辑,第一个编辑命令删除/etc/passwd第三行到末尾的数据,第二条命令搜索bash替换为 blueshell。

直接修改文件内容(危险动作)

代码语言:javascript复制
[root@localhost ~]# cat test
line one.
line two.
line three.
line four.
line five.

加i参数就是直接修改

代码语言:javascript复制
[root@localhost ~]# sed -i 's/.$/!/g' test
[root@localhost ~]# cat test
line one!
line two!
line three!
line four!
line five!

利用 sed 直接在最后一行加入 # test

代码语言:javascript复制
[root@localhost ~]# sed -i '$a# test' test
[root@localhost ~]# cat test
line one!
line two!
line three!
line four!
line five!
# test

Linux三剑客之awk

使用方法

代码语言:javascript复制
awk '{pattern   action}' {filenames}

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花 括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是 要表示的正则表达式,用斜杠括起来。

awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进 行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。

通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文 本。

awk 的原理

代码语言:javascript复制
[root@localhost ~]# awk -F: '{print $0}' /etc/passwd

执行 awk 时,它依次对/etc/passwd 中的每一行执行 print 命令

代码语言:javascript复制
[root@localhost ~]# awk -F":" '{print $1}' /etc/passwd
[root@localhost ~]# awk -F":" '{print $1 $3}' /etc/passwd
[root@localhost ~]# awk -F":" '{print $1" " $3}' /etc/passwd
[root@localhost ~]# awk -F":" '{print "username:"$1"ttuid:" $3}'/etc/passwd

-F参数:指定分隔符,可指定一个或多个

print 后面做字符串的拼接

实例一:只查看test.txt文件(100行)内第20到第30行的内容(企业面试)

代码语言:javascript复制
[root@localhost ~]# seq 100 > test.txt
[root@localhost ~]# awk '{if(NR>=20 && NR<=30) print $1}' test.txt
20
21
22
23
24
25
26
27
28
29
30

实例二:已知test.txt文件内容为

代码语言:javascript复制
[root@localhost ~]# cat test.txt
I am aaron, my qq is 1234567

请从该文件中过滤出'aaron'字符串与1234567,最后输出的结果为:aaron 1234567

代码语言:javascript复制
[root@localhost ~]# awk -F '[ ,] ' '{print $3" "$8}' test.txt #用[]可以放多个分隔符
aaron 1234567
等效
[root@localhost ~]# awk -F ',' '{print $1" "$2}' test.txt|awk '{print $3 " "$7}'

BEGIN 和 END 模块

实例一:统计/etc/passwd的账户人数

代码语言:javascript复制
awk 'BEGIN {count=0;print "[start] user count is ",count}{count  ;print $0}END{print "[end] user count is ",count}' /etc/passwd

count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多 个语句,以;号隔开。这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0

代码语言:javascript复制
[root@localhost ~]# awk '{count  ;print $0;} END{print "user count is",count}' /etc/passwd

实例二:统计某个文件夹下的文件占用的字节数

代码语言:javascript复制
[root@localhost ~]# ll | awk 'BEGIN {size=0} {size=size $5} END{print "sizeis ",size}'
size is 1468
代码语言:javascript复制
[root@localhost ~]# ll | awk 'BEGIN {size=0} {size=size $5} END{print"sizeis",size/1024/1024,"M"}'
size is 0.00139999 M

awk运算符

运算符

描述

赋值运算符

= = -= = /= %= ^= *=

赋值语句

逻辑运算符

逻辑或

&&

逻辑与

正则运算符

~ !~

匹配正则表达式和不匹配正则表达式

关系运算符

< <= > >= != ==

关系运算符

算数运算符

-

加,减

* / &

乘,除与求余

- !

一元加,减和逻辑非

^ *

求幂

--

增加或减少,作为前缀或后缀

其他运算符

$

字段引用

空格

字符串链接符

?:

三目运算符

ln

数组中是否存在某键值

awk 赋值运算符:a =5;等价于: a=a 5;其他同类

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{a=5;a =5;print a}'
10

awk逻辑运算符:判断表达式 a>2&&b>1为真还是为假,后面的表达式同理

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{a=1;b=2;print (a>2&&b>1,a=1||b>1)}'
0 1

awk正则运算符:

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{a="100testaa";if(a~/100/) {print "OK"}}'
OK

关系运算符:

如: > < 可以作为字符串比较,也可以用作数值比较,关键看操作数如果是字符串就会转换为字符串比 较。两个都为数字 才转为数值比较。字符串比较:按照ascii码顺序比较。

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{a="11";if(a>=9){print"OK"}}'
[root@node-1 ~]# awk 'BEGIN{a=11;if(a>=9){print"OK"}}'
OK
[root@node-1 ~]# awk 'BEGIN{a;if(a>=b){print"OK"}}'
OK

awk 算术运算符:

说明,所有用作算术运算符进行操作,操作数自动转为数值,所有非数值都变为0。

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{a="b";print a  ,  a}'
0 2
[root@node-1 ~]# awk 'BEGIN{a="20b4";print a  ,  a}'
20 22

这里的a , a与javascript语言一样:a 是先赋值加 ; a是先 再赋值

三目运算符 ?:

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'
ok
[root@node-1 ~]# awk 'BEGIN{a="b";print a=="c"?"ok":"err"}'
err

常用 awk 内置变量

变量名

属性

$0

当前记录

1 n

当前记录的第n个字段

FS

输入字段分割符 默认是空格

RS

输入记录分割符 默认为换行符

NF

当前记录中的字段个数,就是有多少列

NR

已经读出的记录数,就是行号,从1开始

OFS

输出字段分割符 默认也是空格

ORS

输出的记录分割符 默认为换行符

注:内置变量很多,参阅相关资料

字段分隔符 FS

FS="t" 一个或多个 Tab 分隔

代码语言:javascript复制
[root@node-1 ~]# cat tab.txt
aa bb cc
[root@node-1 ~]# awk 'BEGIN{FS="t "}{print $1,$2,$3}' tab.txt
aa bb cc

FS="[[:space:] ]" 一个或多个空白空格,默认的,匹配到不符合的就停止

代码语言:javascript复制
[root@node-1 ~]# awk -F [[:space:] ] '{print $1,$2,$3,$4,$5}' tab.txt
aa bb cc
[root@node-1 ~]# awk -F [[:space:] ] '{print $1,$2}' tab.txt
aa bb

FS="[" ":] " 以一个或多个空格或:分隔

代码语言:javascript复制
[root@node-1 ~]# awk -F [" ":]  '{print $1,$2,$3}' hello.txt
root x 0

字段数量 NF :显示满足用:分割,并且有8个字段的

代码语言:javascript复制
[root@node-1 ~]# awk -F ":" 'NF==8{print $0}' hello.txt
bin:x:1:1:bin:/bin:/sbin/nologin:888

记录数量 NR

代码语言:javascript复制
[root@node-1 ~]# ifconfig br0 | awk -F [" ":]  'NR==2{print $3}'
192.168.0.241

RS 记录分隔符变量

将 FS 设置成"n"告诉 awk 每个字段都占据一行。通过将 RS 设置成"",还会告诉 awk每个地址记录都由 空白行分隔。

代码语言:javascript复制
[root@node-1 ~]# cat awk.txt
#!/bin/awk
BEGIN {
FS="n"
RS=""
}
{
print $1","$2","$3
}
[root@node-1 ~]# awk -f awk.txt recode.txt

在""分割符之内,符合n分割的会被打印出来

OFS 输出字段分隔符

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{FS=":";OFS="#"}{print $1,$2,$3}' hello.txt
root#x#0
bin#x#1

ORS 输出记录分隔符

代码语言:javascript复制
[root@node-1 ~]# cat awk.txt
#!/bin/awk
BEGIN {
FS="n"
RS=""
ORS="nn"
}
{
print $1","$2","$3
}
[root@node-1 ~]# awk -f awk.txt recode.txt
Jimmy the Weasel,100 Pleasant Drive,San Francisco,CA 123456
Big Tony,200 Incognito Ave.,Suburbia,WA 64890

awk正则

元字符

功能

示例

解释

^

首航定位符

/^root/

匹配所有以root开头的行

行尾定位符/root/

匹配所有以root结尾的行

.

匹配任意单个字符

/r..t/

匹配字母r,然后两个任意字符,再以t结尾的行

*

匹配0个或多个前导字符(包括回车)

/a*ool/

匹配0个或多个a之后紧跟着ool的行,比如ool,aaaaool 等

匹配1个或多个前导字符

/a b/

ab, aaab

?

匹配0个或1个前导字符

/a?b/

b,ab

[]

匹配指定字符组内的任意一个字符

/^[abc]/

匹配以a或b或c开头的行

[^]

匹配不在指定字符组内任意一个字符

/^[^abc]/

匹配不以字母a或b或c开头的行

()

子表达式组合

/(rool) /

表示一个或多个rool组合,当有一些字符需要组合时,使用括号括起来

或者的意思

/(root)

B/

匹配root或者B的行

转义字符

/a///

匹配a//

~,!~

匹配,不匹配的条件语句

$1~/root/

匹配第一个字段包含字符 root的所有记录

x{m}x{m,}x{m,n}

x重复m次x重复至少m次x重复至少m次,但是不超过n次

/(root) {3}//(root) {3,}//(root) {3,6}/

正则应用

规则表达式

awk '/REG/{action} ' file ,/REG/为正则表达式,可以将$0 中,满足条件的记录送入到:action 进行处理

代码语言:javascript复制
[root@node-1 ~]# awk '/root/{print$0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@node-1 ~]# awk -F ":" '$5~/root/{print$0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@node-1 ~]# ifconfig br0 | awk 'BEGIN{FS="[[:space:]:] "}NR==2{print$3}'
192.168.0.241

布尔表达式

awk '布尔表达式{action}' file 仅当对前面的布尔表达式求值为真时, awk 才执行代码块。

代码语言:javascript复制
[root@node-1 ~]# awk -F: '$1=="root"{print$0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@node-1 ~]# awk -F: '($1=="root")&&($5=="root"){print$0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash

awk 的 if、循环和数组

if

条件语句

awk 提供了非常好的类似于 C 语言的 if 语句。

代码语言:javascript复制
{
    if ($1=="foo"){
    if ($2=="foo"){
        print"uno"
    }else{
        print"one"
    }
  }elseif($1=="bar"){
    print "two"
  }else{
    print"three"
  }
}

使用 if 语句还可以将代码:

代码语言:javascript复制
! /matchme/ { print $1 $3 $4 }

转换成:

代码语言:javascript复制
{
    if ( $0 !~ /matchme/ ) {
        print $1 $3 $4
    }
}

while

循环结构

我们已经看到了 awk 的 while 循环结构,它等同于相应的 C 语言 while 循环。 awk 还有"do...while"循 环,它在代码块结尾处对条件求值,而不像标准 while 循环那样在开始处求值。

它类似于其它语言中的"repeat...until"循环。以下是一个示例:

do...while 示例

代码语言:javascript复制
{
    count=1do {
        print "I get printed at least once no matter what"
    } while ( count !=1 )
}

与一般的 while 循环不同,由于在代码块之后对条件求值, "do...while"循环永远都至少执行一次。换句 话说,当第一次遇到普通 while 循环时,如果条件为假,将永远不执行该循环。

for 循环

awk 允许创建 for 循环,它就象 while 循环,也等同于 C 语言的 for 循环:

代码语言:javascript复制
for ( initial assignment; comparison; increment ) {
    code block
}

以下是一个简短示例:

代码语言:javascript复制
for ( x=1;x<=4;x   ) {
    print "iteration", x
}

break 和 continue

此外,如同 C 语言一样, awk 提供了 break 和 continue 语句。使用这些语句可以更好地控制 awk 的 循环结构。

代码语言:javascript复制
#!/bin/awk
BEGIN{
x=1
while(1) {
    print "iteration",x
    if ( x==10 ){
        break
    }
    x  
}
}

continue 语句补充了 break

代码语言:javascript复制
x=1
while (1) {
        if ( x==4 ) {
        x  
        continue
    }
    print "iteration", x
    if ( x>20 ) {
        break
    }
    x  
}

continue在for中使用

代码语言:javascript复制
#!/bin/awk
BEGIN{
for (x=1;x<=21;x  ){
if (x==4){
    continue
}
    print "iteration",x
}
}

数组

AWK 中的数组都是关联数组,数字索引也会转变为字符串索引

在awk中,数组叫关联数组,与我们在其它编程语言中的数组有很大的区别。关联数组,简单来说,类 似于python语言中的dict、java语言中的map,其下标不再局限于数值型,而可以是字符串,即下标为 key,value=array[key]。竟然为key,那其下标也不再是有序的啦。

代码语言:javascript复制
#!/bin/awk
BEGIN{
    cities[1]="beijing"
    cities[2]="shanghai"
    cities["three"]="guangzhou"
    for( c in cities) {
        print cities[c]
    }
    print cities[1]
    print cities["1"]
    print cities["three"]
}

用 awk 中查看服务器连接状态并汇总

代码语言:javascript复制
[root@node-1 ~]# netstat -an|awk '/^tcp/{  s[$NF]}END{for(a in s)printa,s[a]}'
LISTEN 8
ESTABLISHED 1

常用字符串函数

字符串函数的应用

在 info 中查找满足正则表达式, /[0-9] / 用”!”替换,并且替换后的值,赋值给 info

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9] /,"!",info);print info}'
this is a test!test!

如果查找到数字则匹配成功返回 ok,否则失败,返回未找到

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{info="this is a test2010test!";printindex(info,"test")?"ok":"no found";}'
ok

从第 4 个 字符开始,截取 10 个长度字符串

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{info="this is a test2010test!";print
substr(info,4,10);}'
s is a tes

分割 info,动态创建数组 tA,awk for …in 循环,是一个无序的循环。 并不是从数组下标1…n 开始

代码语言:javascript复制
[root@node-1 ~]# awk 'BEGIN{info="this is a test";split(info,tA," ");print
length(tA);for(k in tA){print k,tA[k];}}'
4
4 test
1 this
2 is
3 a

0 人点赞