Linux文本操作相关命令

本文带来Linux文本文件操作和文本内容操作常用方法。

一、文本文件操作

1.1 cat&&tac

直接查看一个文件的内容可以使用cat,tac,nl这几个指令

cat(concatenate)参数:

-n 或 --number:由 1 开始对所有输出的行数编号。

-b 或 --number-nonblank:和 -n 相似,只不过对于空白行不编号。

-s 或 --squeeze-blank:当遇到有连续两行以上的空白行,就代换为一行的空白行。

-v 或 --show-nonprinting:使用 ^ 和 M- 符号,除了 LFD 和 TAB 之外。

-E 或 --show-ends : 在每行结束处显示 $。

-T 或 --show-tabs: 将 TAB 字符显示为 ^I。

-A, --show-all:等价于 -vET。

**-e:**等价于"-vE"选项;

**-t:**等价于"-vT"选项;

cat是concatenate的缩写,其功能时间一个文件的内容连续的输出。该命令适合看行数较少的文件。另外,需要查看一般DOS文件时,可以通过-A选项来显示换行符和[tab](及特殊符号)

**tac(**反向输出):

1
2
3
4
5
6
7
8
[root@layne laydir]# cat a.txt
141232afsg
zfghahhh
aaaaa
[root@layne laydir]# tac a.txt
aaaaa
zfghahhh
141232afsg

与上面的cat命令进行比较,是由最后一行先显示。

tac功能与cat类似,但是是由文件最后一行反向连续输出到屏幕上。

1.2 more&less

more会在最后一行输出目前按显示内容的所占百分比,在现实过程中我们还可以输入以下命令进行进一步操作:

  • 向下翻页ctrl+f,向上翻页ctrl+b
  • 空格(space):向下翻页
  • 回车(Enter):向下翻一行
  • “/字符串”:在当前显示内容中线下查询字符串内容
  • “:f”:立即显示出文件名以及目前显示的行数
  • “q”:离开显示内容
  • “b”或[ctrl]-b:代表回翻,该操作仅对文件有效

例如:more /etc/profile

less 与 more 类似,但使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会加载整个文件。(在查看大文件时或内存不够时,可用less命令)

1.3 head

取出前面几行

1.4 tail

tail可以监控一个文件,默认显示后10行

-f 表示持续监测,这个功能可以用来监控日志或进行调试

1.5 管道

“|”管道符,意思为管道左侧的输出作为右侧的输入,常和grep搭配使用

grep一般用作过滤。

比如:

  • ps -ef | grep vim 显示带有vim的进程信息
  • ps aux | head -n 10显示前10个进程

管道可以有多个,作用以此类推。

echo "/" | ls -l 会显示当前目录下的内容,不会显示根目录下的内容

两个参数:

- v代表不包含

- i代表包含

1.6 Xargs

将前面输出作为后面命令的参数

xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。

之所以能用到这个命令,关键是由于很多命令不支持|管道来传递参数,而日常工作中有有这个必要,所以就有了 xargs 命令,例如:

echo "/" | xargs ls -l 就可以输出根目录下的内容,而echo "/" | ls -l 则不行

echo "a.txt"|vim 可以进入a.txt编辑,而echo "a.txt"|vim则不行

1.7 数据重定向

标准输入(stdin):编号为0

标准输出(stdout):编号为1

标准错误输出(stderr):编号为2

1>:以覆盖的方法,将正确的数据输出到文件; 

1>>:以累加的方法,将正确的数据输出到文件; 

2>:以覆盖的方法,将错误输出的数据输出到文件; 

2>>:以累加的方法,将错误输出的数据输出到文件; 

只有单独的> 和 >> 也是只能输出正确的信息

可自己尝试以下命令:

1
2
3
4
5
6
ls  -l  >>  ok1.log
ls -l > ok2.log
ls hello 2>/root/err.log
ls hello / 1>/root/log.log 2>/root/err.log
ls 1>/dev/null
ls 2>/tmp/err.log

既向控制台输出,也向文件写入

ls -l / | tee ok2.log

tee命令,将输入分成两个输出

tee只能把正确的数据放入文件里面

tee 把原来的数据清空,把最新的数据写到里面。

二、文本内容操作

2.1 cut

cut:显示切割的行数据

  • -s:不显示没有分隔符的行(过滤脏数据)
  • -d:指定分隔符对源文件的行进行分割
  • -f:选定显示哪些列
    • m-n: m列到n列
    • -n :第一列到n列
    • m- :第m列到最后列
    • n :第n列

例如(默认列数是从1开始):

  • cut -d ":" -f 1 passwd 对passwd用:分割,然后获取第一列
  • cut -s -d ":" -f 1 passwd 对passwd用:分割,然后获取第一列,且不显示没有分隔符的行(如果有的行没有分隔符,不加-s会输出会包含脏数据,加了-s后就不会打印没有分隔符的行)
  • cut -sd ":" -f 1 passwdcut -s -d ":" -f 1 passwd
  • 不能为cut -ds ":" -f 1 passwd,因为d后面要跟分隔符
  • cut -d ":" -f 3-5 passwd:作为分隔符切割passwd,输出从第3列到第5列
  • cut -d ":" -f 1,3,5 passwd:作为分隔符切割passwd,输出1、3、5列
  • cut -d ":" -f -2 passwd:作为分隔符切割passwd,输出前两列
  • cut -d ":" -f 3- passwd:作为分隔符切割passwd,输出第三列到最后一列
  • cut -d ":" -f 3- --output-delimiter=".." passwd 指定输出的分隔符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
[root@layne laydir]# cp /etc/passwd ./
[root@layne laydir]# cut -d ":" -f 1 passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
uucp
operator
games
gopher
ftp
nobody
vcsa
saslauth
postfix
sshd
ntp
lucy
liubei
gem
mysql
[root@layne laydir]# cut -d ":" -f 3- --output-delimiter=".." passwd
0..0..root../root../bin/bash
1..1..bin../bin../sbin/nologin
2..2..daemon../sbin../sbin/nologin
3..4..adm../var/adm../sbin/nologin
4..7..lp../var/spool/lpd../sbin/nologin
5..0..sync../sbin../bin/sync
6..0..shutdown../sbin../sbin/shutdown
7..0..halt../sbin../sbin/halt
8..12..mail../var/spool/mail../sbin/nologin
10..14..uucp../var/spool/uucp../sbin/nologin
11..0..operator../root../sbin/nologin
12..100..games../usr/games../sbin/nologin
13..30..gopher../var/gopher../sbin/nologin
14..50..FTP User../var/ftp../sbin/nologin
99..99..Nobody../../sbin/nologin
69..69..virtual console memory owner../dev../sbin/nologin
499..76.."Saslauthd user"../var/empty/saslauth../sbin/nologin
89..89..../var/spool/postfix../sbin/nologin
74..74..Privilege-separated SSH../var/empty/sshd../sbin/nologin
38..38..../etc/ntp../sbin/nologin
500..500..../usr/lucy../bin/bash
501..501..../home/liubei../bin/bash
502..0..../home/gem../bin/bash
27..27..MySQL Server../var/lib/mysql../bin/false

2.2 sort

排序:字典序和数值序

sort:排序文件的行

可选参数如下:

- n:按数值排序

- r:倒序 reverse

- t:自定义分隔符

- k:选择排序列

- f:忽略大小写

现在,我们创建一个sort.txt,文件内容如下:

1
2
3
4
5
6
7
a b 1
dfdsa fdsa 15
fds fds 6
fdsa fdsa 8
fda s 9
aa dd 10
h h 11

sort sort.txt是默认按字典排序:

1
2
3
4
5
6
7
8
[root@layne laydir]# sort sort.txt
aa dd 10
a b 1
dfdsa fdsa 15
fda s 9
fdsa fdsa 8
fds fds 6
h h 11

指定字段分隔符,按照第2个字段的字典序排序:

1
2
3
4
5
6
7
8
[root@layne laydir]# sort -t ' ' -k 2 sort.txt
a b 1
aa dd 10
fds fds 6
dfdsa fdsa 15
fdsa fdsa 8
h h 11
fda s 9

指定字段分隔符,按照第3个字段的值数值序排序:

1
2
3
4
5
6
7
8
[root@layne laydir]# sort -t ' ' -k 3 -n sort.txt
a b 1
fds fds 6
fdsa fdsa 8
fda s 9
aa dd 10
h h 11
dfdsa fdsa 15

指定字段分隔符,按照第3个字段的值数值倒序

1
2
3
4
5
6
7
8
[root@layne laydir]# sort -t ' ' -k 3 -nr sort.txt
dfdsa fdsa 15
h h 11
aa dd 10
fda s 9
fdsa fdsa 8
fds fds 6
a b 1

将结果写入到新的文件中:

1
[root@layne laydir]# sort -t " " -k 3 -nr sort.txt >> test1.txt

2.3 wc

格式:wc [选项列表]… [文件名列表]…

DESCRIPTION 描述:

对每个文件输出行、单词、和字节统计数,若不指定文件名称、或是所给予的文件名为"-",则wc指令会从标准输入设备读取数据。

-c, --bytes, --chars 输出字节统计数。

-l, --lines 输出换行符统计数。

​ -L, --max-line-length 输出最长的行的长度。

-w, --words 输出单词统计数。

例如:

1
2
3
4
5
6
7
8
9
10
11
[root@layne laydir]# cp sort.txt wc.txt
[root@layne laydir]# cat wc.txt
a b 1
dfdsa fdsa 15
fds fds 6
fdsa fdsa 8
fda s 9
aa dd 10
h h 11
[root@layne laydir]# wc wc.txt
7 21 66 wc.txt

上面命令,输出结果为7 21 66 wc.txt,其中,7是行数,21是单词数,66是字节数

1
2
3
4
5
6
7
8
[root@layne laydir]# wc -l wc.txt
7 wc.txt
[root@layne laydir]# cat wc.txt | wc -l
7
[root@layne laydir]# wc -w wc.txt
21 wc.txt
[root@layne laydir]# wc -c wc.txt
66 wc.txt

2.4 sed

sed 在不打开文件的情况下执行交互,来修改文件。

sed即行编辑器

sed [选项] 如下:

  • -n:静默模式,不再默认显示模式空间的内容(看例子理解)
  • -i直接修改源文件
  • -e Script -e Script:可以同时执行多个脚本
  • -f /path/to/sed_script:执行文件中的sed脚本
  • -r:表示使用扩展正则表达式
  • a\string:在指定的行后追加新行,内容为string

n \n:用于换行

  • i\string:在指定行添加新行,内容是string
  • r file:将指定的文件内容添加到符合条件的行的位置
  • w file:将地址指定的范围内的行另存至指定文件
  • s/string1/string2/:查找并替换,默认只替换每行第一次模式匹配到的字符串

n g:行内全局替换 (看例子)

n i:忽略大小写

n s///,s###,s@@@:用于避免字符冲突

n () \1\2

动作说明

  • a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)
  • c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行
  • d :删除, d 后面不接任何字符串
  • i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
  • p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行
  • s :取代,可以直接进行取代的工作!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!

让我们来尝试一下吧

创建sed.txt,内容如下:

1
2
3
Authentication improvements when using an HTTP proxy server.
Support for POSIX-style filesystem extended attributes.
YARN's REST APIs now support write/modify operations.

第一行下插入一行 sed "1a\hello world" sed.txt(没有修改源文件):

1
2
3
4
5
6
7
8
9
[root@layne laydir]# cat sed.txt
Authentication improvements when using an HTTP proxy server.
Support for POSIX-style filesystem extended attributes.
YARN's REST APIs now support write/modify operations.
[root@layne laydir]# sed "1a\hello world" sed.txt
Authentication improvements when using an HTTP proxy server.
hello world
Support for POSIX-style filesystem extended attributes.
YARN's REST APIs now support write/modify operations.

加上-i直接修改源文件sed -i "1a\hello world" sed.txt

删除第2行sed -i "2d" sed.txt

1
2
3
4
5
6
7
8
9
10
[root@layne laydir]# cat sed.txt
Authentication improvements when using an HTTP proxy server.
hello world
Support for POSIX-style filesystem extended attributes.
YARN's REST APIs now support write/modify operations.
[root@layne laydir]# sed -i "2d" sed.txt
[root@layne laydir]# cat sed.txt
Authentication improvements when using an HTTP proxy server.
Support for POSIX-style filesystem extended attributes.
YARN's REST APIs now support write/modify operations.

删除文档中的所有内容sed "d" sed.txt (不修改原文件)

匹配行中包含0-9任意一个字符的行,默认匹配的行打印(匹配的行打印两次),没匹配的行也打印(匹配的行打印一次),命令为sed "/[0-9]/p" sed.txt

1
2
3
4
5
6
7
8
9
10
11
[root@layne laydir]# cat sed.txt
uthentication improvements when using an HTTP proxy server.
Support for POSIX-style filesystem extended attributes.
hello2world
YARN's REST APIs now support write/modify operations.
[root@layne laydir]# sed "/[0-9]/p" sed.txt
uthentication improvements when using an HTTP proxy server.
Support for POSIX-style filesystem extended attributes.
hello2world
hello2world
YARN's REST APIs now support write/modify operations.

匹配行中包含0-9任意一个字符的行,只打印找到的行,加-n 实现sed -n "/[0-9]/p" sed.txt

1
2
3
4
5
6
7
[root@layne laydir]# cat sed.txt
uthentication improvements when using an HTTP proxy server.
Support for POSIX-style filesystem extended attributes.
hello2world
YARN's REST APIs now support write/modify operations.
[root@layne laydir]# sed -n "/[0-9]/p" sed.txt
hello2world

将filesystem替换为FS命令为sed "s/filesystem/FS/" sed.txt (默认区分大小写,且只替换每一行匹配到的第一个):

1
2
3
4
5
6
7
8
[root@layne laydir]# cat sed.txt
uthentication improvements when using an HTTP proxy server.
Support FILESysTem for POSIX-style filesystem extended filesystem attributes.
YARN's REST APIs now filesystem support write/modify operations.
[root@layne laydir]# sed "s/filesystem/FS/" sed.txt
uthentication improvements when using an HTTP proxy server.
Support FILESysTem for POSIX-style FS extended filesystem attributes.
YARN's REST APIs now FS support write/modify operations.

将filesystem替换为FS,忽略大小写sed "s/filesystem/FS/i" sed.txt

1
2
3
4
5
6
7
8
[root@layne laydir]# cat sed.txt
uthentication improvements when using an HTTP proxy server.
Support FILESysTem for POSIX-style filesystem extended filesystem attributes.
YARN's REST APIs now filesystem support write/modify operations.
[root@layne laydir]# sed "s/filesystem/FS/i" sed.txt
uthentication improvements when using an HTTP proxy server.
Support FS for POSIX-style filesystem extended filesystem attributes.
YARN's REST APIs now FS support write/modify operations.

将filesystem替换为FS,不仅忽略大小写还要行内全局替换sed "s/filesystem/FS/gi" sed.txt

1
2
3
4
5
6
7
8
[root@layne laydir]# cat sed.txt
uthentication improvements when using an HTTP proxy server.
Support FILESysTem for POSIX-style filesystem extended filesystem attributes.
YARN's REST APIs now filesystem support write/modify operations.
[root@layne laydir]# sed "s/filesystem/FS/gi" sed.txt
uthentication improvements when using an HTTP proxy server.
Support FS for POSIX-style FS extended FS attributes.
YARN's REST APIs now FS support write/modify operations.

新建一个文件sed1.txt,输入以下内容:

1
2
hello world,hahha,This is hiaccy2 ideas
I am 24 years old,lalala

将sed1.txt的所有数字替换为5,sed "s/[0-9]/5/g" sed1.txt

1
2
3
[root@layne laydir]# sed "s/[0-9]/5/g" sed1.txt
hello world,hahha,This is hiaccy5 ideas
I am 55 years old,lalala

将hiaccy2改为hiaccy9,先看下面的命令:

1
2
3
[root@layne laydir]# sed  "s/2/9/"  sed1.txt
hello world,hahha,This is hiaccy9 ideas
I am 94 years old,lalala

会发现,发现将所有匹配的都修改了(注意并未修改原文件),第二行的24被替换为了94。

更精确匹配方案的写法应该为如下命令:

1
2
3
[root@layne laydir]# sed  "s/hiaccy[0-4]/9/"  sed1.txt
hello world,hahha,This is 9 ideas
I am 24 years old,lalala

**但是还存在问题,匹配后被修改内容问匹配出的部分,范围过大。**解决办法:反向引用

用命令sed "s/\(hiaccy\)[0-6]/\19/" sed1.txt

1
2
3
[root@layne laydir]# sed "s/\(hiaccy\)[0-6]/\19/" sed1.txt
hello world,hahha,This is hiaccy9 ideas
I am 24 years old,lalala

分析:

sed "s/\(hiaccy\)[0-6]/\19/" sed1.txt 的结构划分为:

  • sed 命令
  • s/ 替换的前缀(第一个分割标志)
  • \(hiaccy\) 其实就是hiaccy,括号用\(\),就是转义字符,查找的还是hiaccy
  • [0-6] 通配符数字1~6
  • / 替换的第二个分割标志
  • \1 表示前面的第一个转义内容,即\(hiaccy\)
  • 9 把在第一个分割标志和第二个分割标志中间 ,除了\1表示的之外的内容,替换为9
  • /第三个分割标志

再看一个例子,把sed1.txt的中的world替换为woABCld:

1
2
3
[root@layne laydir]# sed "s/\(wo\)r\(ld\)/\1ABC\2/" sed1.txt
hello woABCld,hahha,This is hiaccy2 ideas
I am 24 years old,lalala

如果加上-r,就不用转义字符了:

1
2
3
[root@layne laydir]# sed -r "s/(wo)r(ld)/\1ABC\2/" sed1.txt
hello woABCld,hahha,This is hiaccy2 ideas
I am 24 years old,lalala

查找/etc/profile中包含PATH的行,将这些行写到指定的文件:hello.log中sed -n "/PATH/w hello.log" /etc/profile

2.5 awk

awk是一个强大的文本分析工具,相对于grep查找,sed编辑,awk在对数据分析并生成报告时更为强大。

awk把文件逐行读入,以空格和制表符作为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk -F ‘{pattern + action}’ {filenames}

  • 支持自定义分隔符

  • 支持正则表达式匹配

  • 支持自定义变量,数组 a[1] a[tom] map(key)

  • 支持内置变量

    • ARGC 命令行参数个数
    • ARGV 命令行参数排列
    • ENVIRON 支持队列中系统环境变量的使用
    • FILENAME awk浏览的文件名
    • FNR 浏览文件的记录数
    • FS 设置输入域分隔符,等价于命令行 -F选项
    • NF 浏览记录的域的个数
    • NR 已读的记录数
    • OFS 输出域分隔符
    • ORS 输出记录分隔符
    • RS 控制记录分隔符
  • 支持函数

    • print、split、substr、sub、gsub(注意:关键字不要写在“”里面)
  • 支持流程控制语句,类C语言

    • if、while、do/while、for、break、continue

现在,让我们尝试一下吧!

显示全部内容,awk -F ':' '{print $0}' passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@layne laydir]# cp /etc/passwd ./
[root@layne laydir]# awk -F ':' '{print $0}' passwd
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
lucy:x:500:500::/usr/lucy:/bin/bash
liubei:x:501:501::/home/liubei:/bin/bash
gem:x:502:0::/home/gem:/bin/bash
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false

只显示第一列awk -F ':' '{print $1}' passwd

显示第一列与第5列awk -F ':' '{print $1,$5}' passwd

显示第一列与第5列,中间用逗号隔开awk -F ':' '{print $1 "," $5}' passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@layne laydir]# awk -F ':' '{print $1 "," $5}' passwd
root,root
bin,bin
daemon,daemon
adm,adm
lp,lp
sync,sync
shutdown,shutdown
halt,halt
mail,mail
uucp,uucp
operator,operator
games,games
gopher,gopher
ftp,FTP User
nobody,Nobody
vcsa,virtual console memory owner
saslauth,"Saslauthd user"
postfix,
sshd,Privilege-separated SSH
ntp,
lucy,
liubei,
gem,
mysql,MySQL Server

制表符拼接字段awk -F':' ' { print $1"\t" $7} ' passwd

在所有行开始前添加列名name,shell,在最后一行添加"shell,end" :awk -F ':' 'BEGIN{print "name,shell"} {print $1 "," $7} END{print "shell,end"}' passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@layne laydir]# awk -F ':' 'BEGIN{print "name,shell"} {print $1 "," $7} END{print "shell,end"}' passwd
name,shell
root,/bin/bash
bin,/sbin/nologin
daemon,/sbin/nologin
adm,/sbin/nologin
lp,/sbin/nologin
sync,/bin/sync
shutdown,/sbin/shutdown
halt,/sbin/halt
mail,/sbin/nologin
uucp,/sbin/nologin
operator,/sbin/nologin
games,/sbin/nologin
gopher,/sbin/nologin
ftp,/sbin/nologin
nobody,/sbin/nologin
vcsa,/sbin/nologin
saslauth,/sbin/nologin
postfix,/sbin/nologin
sshd,/sbin/nologin
ntp,/sbin/nologin
lucy,/bin/bash
liubei,/bin/bash
gem,/bin/bash
mysql,/bin/false
shell,end

可以先在txt文本上写出来,再粘贴进去

模板

1
2
3
4
5
6
7
8
9
10
awk `BEGIN {
...
}
{
...
}
END {
...
}`
filename

搜索passwd有root关键字的所有行 awk '/root/ {print $0}' passwd

搜索passwd有root关键字的所有行,并在后面打印ok,再打印passwd所有的内容

awk ' /root/ {print $0,"ok"} {print $0}' passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@layne laydir]# awk  ' /root/  {print $0,"ok"}  {print $0}'  passwd
root:x:0:0:root:/root:/bin/bash ok
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin ok
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
lucy:x:500:500::/usr/lucy:/bin/bash
liubei:x:501:501::/home/liubei:/bin/bash
gem:x:502:0::/home/gem:/bin/bash
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false

搜索passwd有root关键字的所有行的第一列,并在后面打印ok,再打印passwd所有的内容

awk -F ':' ' /root/ {print $1,"ok"} {print $0}' passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[root@layne laydir]# awk -F ':'  ' /root/  {print $1,"ok"}  {print $0}'  passwd
root ok
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
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator ok
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
lucy:x:500:500::/usr/lucy:/bin/bash
liubei:x:501:501::/home/liubei:/bin/bash
gem:x:502:0::/home/gem:/bin/bash
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false

统计passwd文件中,(按 “:” 分)每行的行号,每行的列数,对应的完整行内容( $0对应完成的内容)

awk -F ':' '{print NR "-" NF "-" $0}' passwd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@layne laydir]# awk -F ':' '{print NR "-" NF "-" $0}' passwd
1-7-root:x:0:0:root:/root:/bin/bash
2-7-bin:x:1:1:bin:/bin:/sbin/nologin
3-7-daemon:x:2:2:daemon:/sbin:/sbin/nologin
4-7-adm:x:3:4:adm:/var/adm:/sbin/nologin
5-7-lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6-7-sync:x:5:0:sync:/sbin:/bin/sync
7-7-shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8-7-halt:x:7:0:halt:/sbin:/sbin/halt
9-7-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10-7-uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
11-7-operator:x:11:0:operator:/root:/sbin/nologin
12-7-games:x:12:100:games:/usr/games:/sbin/nologin
13-7-gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
14-7-ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
15-7-nobody:x:99:99:Nobody:/:/sbin/nologin
16-7-vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
17-7-saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
18-7-postfix:x:89:89::/var/spool/postfix:/sbin/nologin
19-7-sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
20-7-ntp:x:38:38::/etc/ntp:/sbin/nologin
21-7-lucy:x:500:500::/usr/lucy:/bin/bash
22-7-liubei:x:501:501::/home/liubei:/bin/bash
23-7-gem:x:502:0::/home/gem:/bin/bash
24-7-mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/false

案例:

统计报表:合计每人1月总消费,0:manager(管理员),1:worker(工人)

emp.txt中的内容如下:

1
2
3
4
5
Tom	 0   2020-12-11      car     3000
John 1 2020-01-13 bike 1000
vivi 1 2020-01-18 car 2800
Tom 0 2020-01-20 car 2500
John 1 2020-01-28 bike 3500

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
awk  '{
split($3, date, "-")
if (date[2] == "01") {
map_name_sala[$1]+=$5
if($2=="0"){
map_name_role[$1]="Manager"
}else{
map_name_role[$1]="Worker"
}
}
}
END{
for(name in map_name_sala){
print name"\t"map_name_sala[name]"\t"map_name_role[name]
}
}' emp.txt

解释:

split($3, date, "-") 意思是将第三列按照-分割,赋值给date数组,这样date[2]就是月份。

map_name_salamap_name_role 都是map[key]类型。

执行上述命令后,输出结果为:

1
2
3
vivi	2800	Worker
Tom 2500 Manager
John 4500 Worker