Linux高级文本处理命令
cut
一、cut命令
功能:cut命令可以从一个文本文件/文本流中提取文本列
语法:
cut -d '分割字符' -f fields ##用于有特定分割字符
cut -c 字符区间 ##用于排列整齐的信息
选项与参数:
- -d:后面接分隔字符。与 -f 一起使用;
- -f:依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思
- -c:以字符(charaters)的单位取出固定字符区间
sed
简介:行编辑器
解决的问题:
- 处理文本文件
- 分析日志文件
- 修改配置文件
sed 的处理流程
读入一行到模式空间,理解为一个临时缓冲区
注意:sed 本身就有输出到屏幕这一步
sed的原则
- sed 一次只处理一行内容
- sed 默认不可以改变文件内容(除非重定向或者用 -i 参数)
- sed 可以对所有行进行操作,也可以根据正则选定行
sed 的格式
1、命令行格式
sed [options] 'command' file
options: -e,-n,-i(optuions 为可选项)
-e # 执行多次 sed 命令
-n # 忽略默认输出
-i # 修改文件
command:行定位/正则定位+ sed 命令(操作)
2、脚本格式
sed -f scriptfile file
sed 命令
我们复制一个文件,进行操作,内容如下:(nl 就是输出带行号, -b a 就是把空白行也带上行号)
# nl -b a passwd
1 root:x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
daemon:x:::daemon:/sbin:/sbin/nologin
adm:x:::adm:/var/adm:/sbin/nologin
lp:x:::lp:/var/spool/lpd:/sbin/nologin
sync:x:::sync:/sbin:/bin/sync
shutdown:x:::shutdown:/sbin:/sbin/shutdown halt:x:::halt:/sbin:/sbin/halt
mail:x:::mail:/var/spool/mail:/sbin/nologin
uucp:x:::uucp:/var/spool/uucp:/sbin/nologin
operator:x:::operator:/root:/sbin/nologin
games:x:::games:/usr/games:/sbin/nologin
gopher:x:::gopher:/var/gopher:/sbin/nologin
ftp:x:::FTP User:/var/ftp:/sbin/nologin
nobody:x:::Nobody:/:/sbin/nologin
vcsa:x:::virtual console memory owner:/dev:/sbin/nologin saslauth:x:::Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x::::/var/spool/postfix:/sbin/nologin
sshd:x:::Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ntp:x::::/etc/ntp:/sbin/nologin
tcpdump:x::::/:/sbin/nologin
nscd:x:::NSCD Daemon:/:/sbin/nologin
mysql:x:::MySQL Server:/var/lib/mysql:/bin/bash
apache:x:::Apache:/var/www:/sbin/nologin
dockerroot:x:::Docker User:/var/lib/docker:/sbin/nologin
1、p
sed 'p' passwd ## 打印出文件内容,但是每一行打印出了两行
sed -n 'p' passwd ## 忽略默认输出
2、行定位
定位一行
x:行号
sed -n '10p' passwd ## 定位到第 10 行
nl -b a passwd | sed -n '10p' ## 定位到第 10 行
/pattern/:正则
sed -n '/mysql/p' passwd ## 定位到含 mysql 的行
定位几行
x,y:行号
nl -b a passwd | sed -n '10,20p' ## 定位到第 10-20 行
/pattern/,x:正则
sed -n '/nobody/,/sshd/' ## 定位到含有 nobody 的行到含有 sshd 的这一行
x,y!:不选择这一行
nl passwd | sed -n '10!p' ## 不显示第 10 行的内容
nl passwd | sed -n '10,20!p' ## 不显示 10-20 行的内容
间隔几行
first ~ step(first:开始行,step:步进)
nl -b a passwd | sed -n '1~2p' ## 从第一行开始,每两行打印一次
# sed -n '10p' passwd ## 打印第 行
mail:x:::mail:/var/spool/mail:/sbin/nologin # sed -n '/nobody/p' passwd ## 打印包含 nobody 的行
nobody:x:::Nobody:/:/sbin/nologin # sed -n '6,10p' passwd ## 打印 - 行(包括其中的空白行)
sync:x:::sync:/sbin:/bin/sync
shutdown:x:::shutdown:/sbin:/sbin/shutdown halt:x:::halt:/sbin:/sbin/halt
mail:x:::mail:/var/spool/mail:/sbin/nologin # sed -n '/nobody/,/sshd/p' passwd ## 打印 nobody 那一行到 sshd 那一行
nobody:x:::Nobody:/:/sbin/nologin
vcsa:x:::virtual console memory owner:/dev:/sbin/nologin saslauth:x:::Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x::::/var/spool/postfix:/sbin/nologin
sshd:x:::Privilege-separated SSH:/var/empty/sshd:/sbin/nologin # sed -n '20,/sshd/p' passwd ## 打印从 行到 sshd 这一行
saslauth:x:::Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x::::/var/spool/postfix:/sbin/nologin
sshd:x:::Privilege-separated SSH:/var/empty/sshd:/sbin/nologin # nl -b a passwd | sed -n '1~2p' ## 从第 1 行开始,每 2 行打印一次
1 root:x:0:0:root:/root:/bin/bash
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
9 halt:x:7:0:halt:/sbin:/sbin/halt
11 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
13 games:x:12:100:games:/usr/games:/sbin/nologin
15 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
17 vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
19
21 postfix:x:89:89::/var/spool/postfix:/sbin/nologin
23 ntp:x:38:38::/etc/ntp:/sbin/nologin
25 nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
27 apache:x:48:48:Apache:/var/www:/sbin/nologin
3、行处理命令
基本命令
-a(新增行)/i(插入行)
# nl -b a passwd | sed '3aganziwenganziwen' ## 在第 3 行后面新增行,内容为 ganziwenganziwen
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
ganziwenganziwen
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin # nl -b a passwd | sed '3iganziwenganziwen' ## 在第 3 行前面插入行,内容为 ganziwenganziwen
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
ganziwenganziwen
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 # nl -b a passwd | sed '3,5aganziwenganziwen' ## 在第 3-5 行之间的每一行都新增 ganziwenganziwen
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
ganziwenganziwen
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
ganziwenganziwen
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
ganziwenganziwen
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown # nl -b a passwd | sed '3,5iganziwenganziwen' ## 在第 3-5 行之间的每一行都插入 ganziwenganziwen
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
ganziwenganziwen
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
ganziwenganziwen
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
ganziwenganziwen
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
-c(替换行)
# nl -b a passwd | sed '3c=========' ## 把第 3 行替换成 ========
root:x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
=========
adm:x:::adm:/var/adm:/sbin/nologin
lp:x:::lp:/var/spool/lpd:/sbin/nologin # nl -b a passwd | sed '3,5c=========' ## 把第 3-5 行内所有的内容全部替换成 1 个 ==========
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
=========
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8
9 halt:x:7:0:halt:/sbin:/sbin/halt
-d(删除行)
# nl -b a passwd | sed '3,5d' ## 把 3-5 行全部删除
root:x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
sync:x:::sync:/sbin:/bin/sync
shutdown:x:::shutdown:/sbin:/sbin/shutdown
练习1:修改配置文件
在 /etc/profile 中添加环境变量
这里,我只贴出环境变量文件的后几行,以供对比
……
85 #python3.
PATH=$PATH:$HOME/bin:/usr/local/python3/bin
export PATH
要解决这个问题有俩难点:1、怎么定位最后一行($ 代表最后一行);2、添加用什么命令
sed 命令如下:
# sed '$a export GZW_HOME=XXX\nexport PATH=$PATH:$GZW_HOME' profile ## 里面加了 \n 为换行符
……
#python3.6
PATH=$PATH:$HOME/bin:/usr/local/python3/bin
export PATH
export GZW_HOME=XXX
export PATH=$PATH:$GZW_HOME
这么写有个问题,就是假设我们前面要加 4 个空格,而我们是顶格写出来的,怎么办?
解决办法:中间的我们可以加空格,但是第一行加不了空格,需要加一个 \
# sed '$a\ export GZW_HOME=XXX\n export PATH=$PATH:$GZW_HOME' profile
……
#python3.
PATH=$PATH:$HOME/bin:/usr/local/python3/bin
export PATH
export GZW_HOME=XXX
export PATH=$PATH:$GZW_HOME
注意:这么写只是输出到屏幕的内容修改了,但是我们没有加 options ,所以默认是不会修改到文件内的,那么要直接修改呢?之前我们讲过,要么重定向 ,要么用 -i 参数
# sed -i '$a\ export GZW_HOME=XXX\n export PATH=$PATH:$GZW_HOME' profile # cat profile
……
#python3.
PATH=$PATH:$HOME/bin:/usr/local/python3/bin
export PATH
export GZW_HOME=XXX
export PATH=$PATH:$GZW_HOME
而且,重定向有问题,如果我们直接 > 的话,那么会把文件清空了。我们得用 >> 追加写的方式,但是追加写又有个问题,那就是会把显示的全部追加进去,也就是说,配置文件有俩大段一样的,那么怎么弄呢?
出现这个问题的原因就是因为会把默认输出的内容也追加进去我们加个 -n 参数就 ok
# sed -n '$a\ export GZW_HOME=XXX\n export PATH=$PATH:$GZW_HOME' profile >> profile
练习2:删除空白行
sed '/^$/d' file ## ^ 代表开头,$ 代表结尾
# sed '/^$/d' passwd
练习3:服务器日志处理——服务器 log 中打印 error 信息
sed -n '/Error/p' file ## 用正则匹配到 Error 信息
# sed -n '/Error/p' catalina.out
替换操作:s
分隔符: /
全局替换: g
例如:
sed 's/nologin/login' passwd ## 将文件内每一行的第一个 nologin 替换成 login
sed 's/:/%/g' passwd ## 将文件内所有的 : 替换成 %
# sed 's/nologin/login/' passwd
……
bin:x:1:1:bin:/bin:/sbin/login
daemon:x:2:2:daemon:/sbin:/sbin/login
adm:x:3:4:adm:/var/adm:/sbin/login
lp:x:4:7:lp:/var/spool/lpd:/sbin/login
…… # sed 's/:/%/' passwd ## 只有第一个 : 换成了 %
root%x:0:0:root:/root:/bin/bash
bin%x:1:1:bin:/bin:/sbin/nologin # sed 's/:/%/g' passwd ## 加入 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
练习:取出 ifconfig 命令内的 ip 地址
分两步:1、先找到有 ip 的那一行,2、把那一行的除 ip 外的信息换成空字符串
# ifconfig | sed -n '/inet/p'
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0
inet addr:127.0.0.1 Mask:255.0.0.0 # ifconfig | sed -n '/inet .* Bcast/p' ## 正则里面再筛选 .* 代表中间还有内容,后面有 Bcast
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 # ifconfig | sed -n '/inet .* Bcast/p' | sed 's/inet.*r://' ## 这里升级,把 ip 的前半拉替换成空字符(inet开头,r:结尾)
172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 # ifconfig | sed -n '/inet .* Bcast/p' | sed 's/inet.*r://' | sed 's/Bcast.*//' ## 再把 Bcast 后面的全部替换成空字符
172.17.42.1 # ifconfig | sed -n '/inet .* Bcast/p' | sed 's/\s\+inet.*r://' | sed 's/\s\+Bcast.*//' ## 上述操作有空白出现,利用 \s 代表空白 + 表一个以上符,但是 + 需要转译,所以为 \s\+
172.17.42.1
sed 高级操作
{} :多个 sed 命令,用 ; 分开(实际操作上,{} 并不是必要的,加了没加还是有点区别)
nl passwd | sed '{10,20;s/false/true/}'
n: 读取下一个输入行(用下一个命令处理)
nl passwd | sed '{n;p}'
nl passwd | sed '{p;n}'
nl passwd | sed '{p;n;n}'
也可以用间隔行进行输出
# sed '{1,3p;s/:/%/}' passwd
root:x:::root:/root:/bin/bash
root%x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
bin%x:::bin:/bin:/sbin/nologin
daemon:x:::daemon:/sbin:/sbin/nologin
daemon%x:::daemon:/sbin:/sbin/nologin
adm%x:::adm:/var/adm:/sbin/nologin
lp%x:::lp:/var/spool/lpd:/sbin/nologin
sync%x:::sync:/sbin:/bin/sync
shutdown%x:::shutdown:/sbin:/sbin/shutdown
…… # sed '{1,3d;s/:/%/}' passwd ## 其实不加 {} 也可以
adm%x:::adm:/var/adm:/sbin/nologin
lp%x:::lp:/var/spool/lpd:/sbin/nologin
sync%x:::sync:/sbin:/bin/sync
shutdown%x:::shutdown:/sbin:/sbin/shutdown halt%x:::halt:/sbin:/sbin/halt
……
# nl -b a passwd | sed -n '{n;p}' ## 第一行被越过了,不打印,所以打印 2,4,6……
2 bin:x:1:1:bin:/bin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
8
10 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
12 operator:x:11:0:operator:/root:/sbin/nologin
14 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
16 nobody:x:99:99:Nobody:/:/sbin/nologin
18
20 saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
22 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
24 tcpdump:x:72:72::/:/sbin/nologin
26 mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
28 dockerroot:x:498:497:Docker User:/var/lib/docker:/sbin/nologin # nl -b a passwd | sed -n '{n;n;p}' ## 第一行以及第二行被跳过,所以打印 3,6,9……,跟 nl -b a passwd | sed -n '{3~3p}' 效果一样
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
9 halt:x:7:0:halt:/sbin:/sbin/halt
12 operator:x:11:0:operator:/root:/sbin/nologin
15 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
18
21 postfix:x:89:89::/var/spool/postfix:/sbin/nologin
24 tcpdump:x:72:72::/:/sbin/nologin
27 apache:x:48:48:Apache:/var/www:/sbin/nologin
&:替换固定的字符串,配合替换操作使用
例如:将 passwd 中用户名后添加空格:
sed 's/[a-z_-]\+/& /' passwd
[a-z_-]\+代表每行开头的那堆字母,因为不止一个,所以要加 + ,而且要转译;
& 注意,要加的内容在 & 符号后面,我这里是加了一个空格,可能不是特别明显。其实 & 就是匹配我们最前面的正则出来的东西,然后再在后面加空格
# sed 's/[a-z_-]\+/& /' passwd
root :x:::root:/root:/bin/bash
bin :x:::bin:/bin:/sbin/nologin
daemon :x:::daemon:/sbin:/sbin/nologin
adm :x:::adm:/var/adm:/sbin/nologin
lp :x:::lp:/var/spool/lpd:/sbin/nologin
sync :x:::sync:/sbin:/bin/sync
shutdown :x:::shutdown:/sbin:/sbin/shutdown
将用户名的首字母转换成大写
\u \l \U \L
\u \l:对首字母转大写或小写
\U |L:对首一串字符转大写或小写
例如:要求用户名首字母大写
sed 's/[a-z_-]\+/\u&/' passwd
# sed 's/[a-z_-]\+/\u&/' passwd
Root:x:::root:/root:/bin/bash
Bin:x:::bin:/bin:/sbin/nologin
Daemon:x:::daemon:/sbin:/sbin/nologin
Adm:x:::adm:/var/adm:/sbin/nologin
Lp:x:::lp:/var/spool/lpd:/sbin/nologin
Sync:x:::sync:/sbin:/bin/sync
Shutdown:x:::shutdown:/sbin:/sbin/shutdown
练习:将文件夹下的 .txt 文件名转换为大写
ls *.txt | sed 's/^\w\+/\U&/'
# ll
total
-rw-r----- root root Feb : catalina.out
-rw-r--r-- root root Feb : gzw.txt
-rw-r--r-- root root Feb : Gzw.txt
-rw-r----- root root Jan : mysqld.log
-rw-r--r-- root root Feb : passwd
-rw-r--r-- root root Feb : profile # ls *.txt | sed 's/^\w\+/\U&/'
GZW.txt
GZW.txt # ls | sed 's/.*/\U&/' ## 文件名包括格式全部换成大写
CATALINA.OUT
GZW.TXT
GZW.TXT
MYSQLD.LOG
PASSWD
PROFIL
():
\( \):替换某种部分字符串 ( \1,\2)
s/w1w2w3/w2/
s/w1\(w2\)\(w3\)/\1\2/
可能难以理解,我们搞个 txt 看一哈
# cat gzw.txt
w1w2w3
接下来演示一下:
# cat gzw.txt | sed 's/w1\(w2\)\(w3\)/\1,\2/' ## 可以把括号内的理解为把它暂时取出来,用 \1 代替,第二个就用 \2 代替,中间可以任意家字符,跟替换一样
w2,w3
练习:获取 eth0 的 ip
# ifconfig | sed -n '/inet.*B/p' ## 首先,我们获取到 ip 的这一行
inet addr:172.17.42.1 Bcast:0.0.0.0 Mask:255.255.0.0 # ifconfig | sed -n '/inet.*B/p' | sed 's/inet.*r:\([0-9\.]\+\)\+\s\+B/\1/' ## 后面那俩 ip 也跟着出来了
172.17.42.1cast:0.0.0.0 Mask:255.255.0.0 # ifconfig | sed -n '/inet.*B/p' | sed 's/inet.*r:\([0-9\.]\+\).\+B.*$/\1/'
172.17.42.1
练习:获取 passwd 中的用户名 uid ,gid,jid
sed 's/\(^[a-z_-]\+\):x:\([0-9]\+\):\([0-9]\+\):.*$/\1,\2,\3/' passwd
# sed 's/\(^[a-z_-]\+\):x:\([0-9]\+\):\([0-9]\+\):.*$/\1,\2,\3/' passwd
root,,
bin,,
daemon,,
adm,,
lp,,
sync,,
shutdown,,
r:读取指定文件插入到匹配行
sed '1r 123.txt' abc.txt ## 读文件不会更改文件内容
w:复制匹配行拷贝指定文件里
sed '1w 123.txt' abc.txt ## 写操作会修改目标文件(将 abc.txt 的第一行写入到 123.txt 内,而且是覆盖写)
# cat .txt # cat abc.txt
abc
def
读:
# sed '1r 123.txt' abc.txt ## 读操作,不改变内容
abc def # cat .txt # cat abc.txt
abc
def
写:
# sed '1w 123.txt' abc.txt ## 将 abc.txt 的第一行写入到 123.txt 内
abc
def # cat .txt
abc # cat abc.txt
abc
def
q:退出 sed 使用 q 可以提前退出 sed
# nl passwd | sed '10q'
root:x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
daemon:x:::daemon:/sbin:/sbin/nologin
adm:x:::adm:/var/adm:/sbin/nologin
lp:x:::lp:/var/spool/lpd:/sbin/nologin
sync:x:::sync:/sbin:/bin/sync
shutdown:x:::shutdown:/sbin:/sbin/shutdown halt:x:::halt:/sbin:/sbin/halt
mail:x:::mail:/var/spool/mail:/sbin/nologin # nl passwd | sed '/nologin/q'
root:x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
-e:执行多次 sed 命令
# nl -b a passwd | sed -e '10,20d' -e 's/:/%/g'
root%x%%%root%/root%/bin/bash
bin%x%%%bin%/bin%/sbin/nologin
daemon%x%%%daemon%/sbin%/sbin/nologin
adm%x%%%adm%/var/adm%/sbin/nologin
lp%x%%%lp%/var/spool/lpd%/sbin/nologin
sync%x%%%sync%/sbin%/bin/sync
shutdown%x%%%shutdown%/sbin%/sbin/shutdown halt%x%%%halt%/sbin%/sbin/halt
postfix%x%%%%/var/spool/postfix%/sbin/nologin
sshd%x%%%Privilege-separated SSH%/var/empty/sshd%/sbin/nologin
ntp%x%%%%/etc/ntp%/sbin/nologin
tcpdump%x%%%%/%/sbin/nologin
nscd%x%%%NSCD Daemon%/%/sbin/nologin
mysql%x%%%MySQL Server%/var/lib/mysql%/bin/bash
apache%x%%%Apache%/var/www%/sbin/nologin
dockerroot%x%%%Docker User%/var/lib/docker%/sbin/nologin
小技巧:如果在 sed 命令的正则表达式内,要使用我们的系统变量怎么办呢?两个方式
1.sed命令使用双引号的情况下,使用$var直接引用
$ echo|sed "s/^/$RANDOM.rmvb_/g"
.rmvb_
# 上面例子引用了一个环境变量$RANDOM的值
2.sed命令使用单引号的情况下,使用'"$var"'引用,单引号里面加双引号,全为因为形式的引号
类似,我们可以看到
$ echo|sed 's/^/'"$RANDOM"'.rmvb_/g'
.rmvb_
面试题:
1、修改某个目录下所有包含 aaa 文件的文件名,将 aaa 改成 AAA,目录结构树如下:
# tree
.
├── aaa.txt
├── aba
│ ├── aaaA.txt
│ ├── aaa.txt
│ ├── Abaaa.txt
│ └── ABA.txt
├── Abaaa.txt
└── BBB
├── aaa.txt
└── ABAB.txt
写法:
# find . -name '*aaa*' -exec rename aaa AAA {} \;
# tree
.
├── AAA.txt
├── aba
│ ├── AAAA.txt
│ ├── AAA.txt
│ ├── AbAAA.txt
│ └── ABA.txt
├── AbAAA.txt
└── BBB
├── AAA.txt
└── ABAB.txt
1、修改某个目录下所有文件中包含 aaa,将文件内的 aaa 改成 AAA
步骤:首先把把包含 aaa 的这些文件给找出来,其次再把 aaa 改成 AAA
# grep aaa abc.txt ## 这行命令的意思是,在 abc.txt 内找出有 aaa 的行
aaa
aaaBB # grep aaa -rl . ## 代表递归,在当前目录下找出所有含有 aaa 的文件
./abc.txt
./qwe.txt
./456/lala.txt # sed 's/aaa/AAA/g' `grep aaa -rl .` ## 这里注意要加全局 g ,不加的话,假设有个 aaaaaa ,那么只会替换前面的 aaa
AAA
AAA
AAABB
aaAa
gzw
a
aa
AAaaA
1234
qwe
a
AAA
AAA
A
s
e
AAAA
aa
A
aaA
AAA
aAaa
AAaaAaAAAA
# sed -i 's/aaa/AAA/g' `grep aaa -rl .` ## 真正要修改要加 -i 参数
awk
简介:文本处理工具
解决的问题:
- 一堆文本要分析
- 一堆数据要处理
- 分析服务器日志
同样的,准备一个 passwd 文件
# nl -b a passwd
root:x:::root:/root:/bin/bash
bin:x:::bin:/bin:/sbin/nologin
daemon:x:::daemon:/sbin:/sbin/nologin
adm:x:::adm:/var/adm:/sbin/nologin
lp:x:::lp:/var/spool/lpd:/sbin/nologin
sync:x:::sync:/sbin:/bin/sync
shutdown:x:::shutdown:/sbin:/sbin/shutdown halt:x:::halt:/sbin:/sbin/halt
mail:x:::mail:/var/spool/mail:/sbin/nologin
uucp:x:::uucp:/var/spool/uucp:/sbin/nologin
operator:x:::operator:/root:/sbin/nologin
games:x:::games:/usr/games:/sbin/nologin
gopher:x:::gopher:/var/gopher:/sbin/nologin
ftp:x:::FTP User:/var/ftp:/sbin/nologin
nobody:x:::Nobody:/:/sbin/nologin
vcsa:x:::virtual console memory owner:/dev:/sbin/nologin saslauth:x:::Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x::::/var/spool/postfix:/sbin/nologin
sshd:x:::Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ntp:x::::/etc/ntp:/sbin/nologin
tcpdump:x::::/:/sbin/nologin
nscd:x:::NSCD Daemon:/:/sbin/nologin
mysql:x:::MySQL Server:/var/lib/mysql:/bin/bash
apache:x:::Apache:/var/www:/sbin/nologin
dockerroot:x:::Docker User:/var/lib/docker:/sbin/nologin
内置参数
$0:表示整个当前行
$1:每行第一个字段
$2:每行第二个字段
$n:每行第 n 个字段
awk 的参数:分隔符
-F separator 设定分隔符(默认为空格)
# awk -F ':' '{print $1}' passwd ## 以 : 为分隔符,打印第一列
root
bin
daemon
adm
lp
sync
shutdown
…
打印多个字段
# awk -F ':' '{print $1,$3}' passwd
root
bin
daemon
adm
lp
sync
shutdown # awk -F ':' '{print $1"\t"$3}' passwd
root
bin
daemon
adm
lp
sync
shutdown # awk -F ':' '{print $1"userid:"$3}' passwd
rootuserid:
binuserid:
daemonuserid:
admuserid:
lpuserid:
syncuserid:
shutdownuserid: # awk -F ':' '{printf("Username:%s\tUid=%s\n",$1,$3)}' passwd ## 可以用 printf 函数形式输出
Username:root Uid=
Username:bin Uid=
Username:daemon Uid=
Username:adm Uid=
Username:lp Uid=
Username:sync Uid=
Username:shutdown Uid=6 # awk -F ':' '{print "Username:"$1"\tUid="$3}' passwd ## 和上述效果一致
Username:root Uid=0
Username:bin Uid=1
Username:daemon Uid=2
Username:adm Uid=3
Username:lp Uid=4
Username:sync Uid=5
NR:每行的行号
NF:字段数量(相当于列,一行有多少个列)
FILENAME:正在处理的文件名
# awk -F ':' '{print NR,NF,FILENAME}' passwd ## 第一行 7 列,文件名为 passwd
passwd
passwd
passwd
passwd
passwd
passwd
练习:显示 /etc/passwd 每行的行号,每行的列数对应的用户名
# awk -F ':' '{print "行号:" NR,"列数:"NF,"文件名:"$1}' passwd
行号:1 列数:7 文件名:root
行号:2 列数:7 文件名:bin
行号:3 列数:7 文件名:daemon
行号:4 列数:7 文件名:adm
行号:5 列数:7 文件名:lp
行号:6 列数:7 文件名:sync
行号:7 列数:7 文件名:shutdown # awk -F ':' '{printf("行号:%s列数:%s用户名:%s\n",NR,NF,$1)}' passwd
行号:1列数:7用户名:root
行号:2列数:7用户名:bin
行号:3列数:7用户名:daemon
行号:4列数:7用户名:adm
行号:5列数:7用户名:lp
行号:6列数:7用户名:sync
行号:7列数:7用户名:shutdown
练习:显示 /etc/passwd 中用户 ID > 100 的行号以及用户名
# awk -F ':' '{if ($3>100) print $1,$3}' passwd
saslauth
dockerroot
练习:在服务器的 apache 日志中找出 ip: 139.162.88.63 的访问日期
日志的格式如下:
139.162.88.63 - - [/Feb/::: +] "GET http://clientapi.ipip.net/echo.php?info=1234567890 HTTP/1.1" "-" "Go-http-client/1.1"
149.34.44.174 - - [/Feb/::: +] "GET / HTTP/1.1" "-" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
有两种方式:
# sed -n '/139.162.88.63/p' access_log | awk '{print $1"\t"substr($4,2)}' ## 利用sed 找出行再处理;substr是截取字符串函数,不用的话,从 1 开始,不用的话,会有 [ 出现
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/::: # awk '/139.162.88.63/{print $1"\t"substr($4,2)}' access_log ## 直接先用正则匹配出行
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Jan/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/:::
139.162.88.63 /Feb/:::
逻辑判断式
~,!~ :匹配正则表达式
==,!=,<,> :判断逻辑表达式
# awk -F ':' '$1~/^m.*/{print $1}' passwd ## 以 m 开头的用户名
mysql # awk -F ':' '$1!~/^m.*/{print $1}' passwd ## 不以 m 开头的用户名
root
bin
daemon
adm
lp
sync
shutdown # awk -F ':' '$3>100{print $1"\t"$3}' passwd
saslauth 499
dockerroot 498
扩展格式
command 扩展
BEGIN{print "start"}pattern{awk 命令}END{print "END"} ## 最开始先执行 BEGIN 后面的花括弧内容,再执行 awk 内的,最后再执行 END 花括弧内的
练习:制表显示 /etc/passwd 每行的行号,每行的列数,对应的用户名
# awk -F ':' 'BEGIN{print"User\tLine\tCol"}{print $1"\t"NR"\t"NF}END{"===="FILENAME"===="}' passwd
User Line Col
root
bin
daemon
adm
lp
sync
====passwd====
练习:统计当前文件夹下的文件/文件夹占用的大小
# ll
total
-rw-r--r-- root root Jan : .log
-rw-r--r-- root root Jan : .log
-rw-r--r-- root root Jan : .log
-rw-r--r-- root root Jan : .log
-rw------- root root Feb : heap.bin
drwxr-xr-x root root Jan : scripts
drwxr-xr-x root root Feb : test # ll | awk 'BEGIN{count==0}{count+=$5}END{print count}'
526304379 # ll | awk 'BEGIN{count==0}{count+=$5}END{print count/1024/1024 "Mb"}'
501.923Mb
练习:统计显示 /etc/passwd 的账户总人数
# awk -F ':' 'BEGIN{count==0}{count++}END{print count}' passwd ## 每行其实就是个用户,但是这样写其实是把空行也计算进去了
28 # awk -F ':' 'BEGIN{count==0}$1!~/^$/{count++}END{print count}' passwd ## 用正则排除空行
25
练习:统计显示 /etc/passwd 中 uid > 100 的用户名
# awk -F ':' 'BEGIN{count==0}$3>100{user[count++]=$1}END{for(i=0;i<count;i++) print i,user[i]}' passwd
saslauth
dockerroot
练习:统计 access_log 日志中每个 ip 出现的次数
# awk '{arr[$1]++}END{for(key in arr) print key,arr[key]}' access_log
39.104.135.252
155.138.161.210
64.68.233.90
171.117.239.207
36.78.107.210
177.188.145.39
177.84.43.202
106.15.176.145
103.110.164.134
36.67.146.11
94.241.165.85
37.115.184.19
139.224.15.159
198.20.87.98
103.204.166.138
101.132.97.6
106.14.168.238 3
…
awk vs sed
awk 和 sed 都可以处理文本
awk 侧重于复杂逻辑处理
sed 侧重于正则处理
awk 和 sed 可以共同使用(统计上,awk 占点优势;sed 在修改文件上占优势)
Linux高级文本处理命令的更多相关文章
- Linux 高级文本处理命令
1.2.1 cut命令 cut命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields ## 用于有特定分隔字符 [ ...
- linux——高级文本处理命令之wc、cut、sort
1. wc :Word Count 命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出 1.1 命令格式: wc [选项]文件... 1.2 命令参数: -c 统计字节数. -l ...
- Linux中的高级文本处理命令,cut命令,sed命令,awk命令
1.2.1 cut命令 cut命令可以从一个文本文件或者文本流中提取文本列. cut语法 [root@www ~]# cut -d'分隔字符' -f fields ## 用于有特定分隔字符 [r ...
- Linux(三)高级文本处理命令
一.cut (cut 命令可以从一个文本文件或者文本流中提取文本列 ) 1.cut语法 cut -d '分隔字符' -f fields 用于有特定分隔字符 cut -c 字符区间 ...
- Linux 的文本处理命令一览
grep 基于关键字搜索文本内容 -i 搜索时忽略大小写-n 显示结果所在行数-v 输出不带关键字的行-Ax 在输出的时候包含结果所在行之后的指定行数(x为一个数值,表示输出后面x行)-Bx 在输出的 ...
- DA_06_高级文本处理命令
Linux中没有盘符这个概念,只有一个根目录“/”,所有文件都在它下面:点击计算机,下面存放的都是根目录下的东西: 2.6 文本文件编辑命令 1.cat 命令用于查看纯文本文件(内容较少的:一次性全部 ...
- Linux常用文本处理命令
1.grep命令 echo 'zero\nzo\nzoo' | grep 'z.*o':将匹配以'z'开头以'o'结尾的所有字符串 echo 'zero\nzo\nzoo' | grep 'z.o': ...
- linux常用文本编缉命令(strings/sed/awk/cut)
一.strings strings--读出文件中的所有字符串 二.sed--文本编缉 类型 命令 命令说明 字符串替换 sed -i 's/str_reg/str_rep/' filename 将文件 ...
- Linux之文本处理命令
Sort 将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出. -u 在输出行中去除重复行 -r 改为降序(默认升序) ...
随机推荐
- Python装饰器、生成器、内置函数、json
这周学习了装饰器和生成器,写下博客,记录一下装饰器和生成器相关的内容. 一.装饰器 装饰器,这个器就是函数的意思,连起来,就是装饰函数,装饰器本身也是一个函数,它的作用是用来给其他函数添加新功能,比如 ...
- HDU 2157 矩阵幂orDP
How many ways?? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- Razor视图引擎 语法学习
下面就和大家分享下我在asp.net官网看到的资料,学习到的点语法.1.通过使用@符号,可以直接在html页面中写C#或者VB代码:运行后: 2.页面中的C#或者VB代码都放在大括号中.运行后: 3. ...
- 上传xslx文件设置accept的MIME 类型
.dotx:application/vnd.openxmlformats-officedocument.wordprocessingml.template.docx:application/vnd.o ...
- linux和window是文件挂载
1. 首先在windows下面创建share文件夹并设置共享(右键->属性->共享)2. 确认ubuntu安装了mount.cifs,apt-get install mount.cifs ...
- mahout推荐系统
本章包含以下内容: 首先看一下实战中的推荐系统 推荐引擎的精度评价 评价一个引擎的准确率和召回率 在真实数据集:GroupLens 上评价推荐系统 我们每天都会对喜欢的.不喜欢的.甚至不关心的事情有很 ...
- office2013安装和破解教程
office2013安装和破解教程(非常简单) 工具/原料 ·电脑 ·office2013 ·HEU_KMS_Activator_CH_v7.6a(激活软件) 方法/步骤 1.1下载Microsoft ...
- jsp jsp常用指令
jsp指令是为jsp引擎设计的,他们并不直接产生任何可见输出,而只是告诉引擎如何处理jsp页面中的其余部分. jsp中的指令 page指令 include指令 taglib指令 jsp指令的基本语法 ...
- Java——File类成员方法
body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...
- pandas 常用语句
pandas的功能非常强大,支持类似与sql的数据增.删.查.改,并且带有丰富的数据处理函数: 支持时间序列分析功能:支持灵活处理缺失数据等. pandas的基本数据结构是Series和DataFra ...