这边的所有命令都可以在 “Linux Cheat Sheet - 文件相关” 这篇博文中找到,这里只是将一些程序锅觉得重要的摘出来了而已。
grep
grep:进行字符串数据的比较,然后将符合用户需求的字符串打印出来。grep 在数据中查找一个字符串时,是以整行为单位进行数据的选取的。grep 会分析一行讯息,如果当中有我们所需要的信息,就将这一行显示出来。
grep [-acinv] [-A] [-B] [--color=auto] '搜寻字串' filename
搜寻字串:可以使用基本的正则表达式
filename:可以多个
-A:后面可加数字,为 after 的意思,也就是除匹配的那行显示出来之外,后续的 n 行也显示出来
-B: 与 -A 类似,只是取前面的 n 行
-a:将 binary 文件以 text 文件的方式搜寻数据
-c:计算找到 '搜寻字串' 的次数
-i:忽略字符大小写的差别
-n:输出行号
-v:反向选择,也就是显示出没有'搜寻字串'内容的那一行
--color=auto:将找到的关键字部分加上颜色的显示
# last 中有出现 root 的那一行取出来
last | grep 'root'
# last 中没有出现 root 的那一行取出来
last | grep -v 'root'
# 取出 /etc/man.config 中含 MANPATH 的那几行
grep --color=auto 'MANPATH' /etc/man.config
# 将关键字所在的前两行和后三行也一起显示出来,同时显示行号
dmesg | grep -n -A3 -B2 'eth'
grep -n 't[ae]st' regular_express.txt
# 下面这两条命令是同样的意思
grep '[^a-z]oo' regular_express.txt
grep '[^[:lower:]]' regular_express.txt
# 查找以 the 为开头的行
grep '^the' regular_express.txt
# 查找以小数点为结尾的那一行,由于小数点是特殊字符,所以小数点需要进行转义,也就是使用(\)
grep '\.$' regular_express.txt
# 查找空白行
grep '^$' regular_express.txt
# 统计当前目录及其子目录下的所有文件包含非空白行的行数
grep -c '[^^$]' * # 这个时候 ^ 放在 [] 里头和外头差别不大
grep -c '[^$]' *
# 找到 g...g 的情况(以 g 为开头,以 g 为结尾的内容)
grep 'g.*g' regular_express.txt
# 找到任意数字的行,比如 “7834 test” 就需要找出 7834
grep '[0-9][0-9]*' regular_express.txt
# 找到含两个 o 的字符串,由于 {} 在 shell 中是有特殊的意义,所以需要使用转义字符(\)
grep 'o\{2\}' regular_express.txt
# 找到 g 后面接 2 到 5 个 o,然后再接一个 g 的
grep 'go\{2,5\}g' regular_express.txt
# 找到 g 后面至少接 2 个 o,并且最后再是一个 g 的
grep 'go\{2,\}g' regular_express.txt
# 后面的是通配符,也就是在 doc、txt、pptx、docx 结尾的文件中找 chapter 的行
grep –n 'chapter' {*.doc, *.txt, *.pptx, *.docx}
附:
1. grep 标准的 grep 命令,支持正则表达式
2. egrep 扩展的 grep 命令,支持基本和扩展正则表达式
3. fgrep 快速的 grep 命令,不支持正则表达式,按照字符串的字面意思进行匹配
sed
sed:sed 是一个非交互式文本编辑器,可对文本文件和标准输入进行编辑,标准输入可以来自键盘输入、文件重定向、字符串、变量和管道的文本。sed 可以将数据进行替换、删除、新增、选取特定行等功能。
sed [-nefr] '动作'
-n:使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据都会被列出在屏幕上。但是加上 -n 参数后,只有经过 sed 特殊处理的那一行(或操作)才会被列出来
-e:直接在命令行模式上进行 sed 的动作编辑
-f:直接将 sed 的动作写在一个文件内,-f filename 则可以执行 filename 内的 sed 动作。
-r:sed 的动作支持的是扩展型正则表达式的语法(默认是基础正则表达式语法)
-i:直接修改读取的文件内容,而不是由屏幕输出
动作说明:
n1[,n2] function(动作,必须要以两个单引号括住):对指定行进行操作(n2 没有就表示 n1 这一行,n1 和 n2 都没有表示全部),一般代表选择进行动作的行数,比如 10,20 [动作行为] 表示我的动作需要在 10 到 20 行之间进行。
/pattern/ function:对包含 pattern 的行进行操作,pattern 支持正则,但是对大小写敏感。
/pattern/pattern/ function:对包含两个 pattern 的行进行操作
/pattern/,n2 function:从 pattern 匹配的行到 n2 行之间的行进行操作
n1,/pattern/ function:从 n1 号当 pattern 匹配的行进行操作
n1[,n2]! function:对除 n1 到 n2 行之外的行进行操作(n2 没有则表示除 n1 外的行)
function:直接 function 也是可以的,表示全部的内容
function 有以下这些参数(这边只列出个人觉得常用的,详细地见图):
a:新增,a 的后面可以接字符串,而这些字符串会在新的一行出现(目前的下一行)。
i:插入,i 后面可接字符串,而这些字符串会在新的一行出现(目前的上一行)。
c:替换,c 的后面可以接字符串,这些字符串可以替换 n1,n2 之间的行。
s:替换,可以直接进行替换的工作,使用方式为:sed 's/要被替换的字符串/新的字符串/[n[g]]'。
s 的动作可以搭配正则表达式。这个跟 c 的区别在于,c 是整行,而这个可以是一行中的某段内容。
g 表示把一行中所有匹配的词都被替换为指定单词。在没有 g 的时候,某行的第 1 处匹配并替换之后,就跳转到下 一匹配行。
n 还可以表示替换第几次匹配到的内容。
s 后面还可以跟一个操作哦!
d:删除,后面一般不接参数。
p:打印,也就是将某个选择的数据打印出来,p 通常与 sed -n 一起使用。
=:打印匹配的行号
r:后面跟 filename,表示添加 filename 中内容,如 sed -n '/library/r output' glib.h。
w:表示将取到的内容重定向到 filename 这个文件中,如 sed -n 's/library/hhh/w output' glib.h。
{}:将多个命令组合在一起运行,有先后顺序,用分号隔开。
# 输出 2-5 行的内容,注意添加 -n 参数
cat -n regular_express.txt | sed -n '2,5p'
# 输出的内容中,第 2-5 行被删除了。原本要跟 -e,但是没有 -e 也行
cat -n regular_express.txt | sed '2,5d'
# 删除第 2 行到最后一行,$在sed命令中代表最后一行
cat -n regular_express.txt | sed '2,$d'
# 对输出内容中的空白行进行删除
cat regular_express.txt | sed '/^$/d'
# 在第二行后面加上 drink tea 这一行
cat -n regular_express.txt | sed '2a drink tea'
# 想要添加多行,那么在输入要添加的第一行内容之后,先不要用 ' 结束,而是添加 \,然后输出新的内容。当还想添加第 3 行,那么在最后添加 \,而不是 '。以此类推。
cat -n regular_express.txt | sed '2a drink tea or ......\
pipe quote> drink beer?\
pipe quote> hello world'
# 在第二行前面加上 drink tea 这一行
cat -n regular_express.txt | sed '2i drink tea'
# 将 2-5 行的内容替换为 No 2-5 Number
cat -n regular_express.txt | sed '2,5c No 2-5 Number'
# 下面演示 sed 的替换功能,主要就是只显示 eno1 网卡的 IP 地址
$ ifconfig eno1 | grep 'inet addr'
inet addr:172.16.1.73 Bcast:172.16.1.255 Mask:255.255.255.0
$ ifconfig eno1 | grep 'inet addr' | sed 's/^.*addr://g'
172.16.1.73 Bcast:172.16.1.255 Mask:255.255.255.0
$ ifconfig eno1 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*//g'
172.16.1.73
# 将 regular_express.txt 内每一行结尾为 . 替换为 !。注意这个操作是直接修改 regular_express.txt 这个文件的内容。
sed -i 's/\.$/\!/g' regular_express.txt
# 替换之后并输出
sed -n 's/library/hhh/gp' glib.h
# 将第二次匹配到的内容进行替换并输出
sed -n 's/library/hhh/2p' glib.h
# 将替换的结果输出到 output 文件中
sed -n 's/library/hhh/w output' glib.h
# 将符合模式的行号打印出来
sed –n '/library/=' glib.h
# 将符合模式的行内容和行号打印出来
sed –n –e '/library/p' –e '/library/=' glib.h
# 等价于: sed -n '/library/{p;=}' glib.h
# 在匹配行后面添加 output 中的内容
sed -n '/library/r output' glib.h
# 先打印匹配行,再将匹配行中的 it 替换为 ll,在打印出来
sed -n '/library/{p;s/it/ll/;p}' glib.h
awk
awk:awk 是以行为一次处理的单位,但以字段为最小的处理单位。也就是说将一行数据分成数个 “字段” 来处理(字段的分隔符默认为空格键或者 tab 键),比较适合处理小型的数据处理。awk 可以处理后续接的文件,也可以读取来自前面命令的 standard output(管道的方式)。
awk '条件类型1{动作1} 条件类型2{动作2} ...' filename
# 1. awk 后面跟两个单引号并加上大括号来设置想要对数据进行的处理动作和条件类型。
# 1.1 条件类型:一是使用逻辑运算符进行比较,满足比较的要求就进行紧跟的 {} 中的动作;二是 "/(中间是正则表达式)/"的使用,表示满足这个正则表达式的行则进行紧跟的 {} 中的动作;三是 BEGIN、END 等关键字。
# “条件类型 + {}” 这种方式其实和 sed 的 “定位 + function” 很像,其中这边的条件类型其实也就是相当于对处理的行进行定位。
# 1.2 {} 里面写的主要是各种 Linux 命令,因此当有多个命令的时候需要使用分号将这些命令隔开,或者直接以 Enter 键来隔开两个命令。awk 中还支持 if 条件判断,可实现对条件类型的替换。
# 1.3 动作里面的非变量的文字部分以及 printf 格式这些都需要使用双引号括住。因为单引号已经是 awk 命令的固定用法了。
# 1.4 与 bash、shell 的变量不同,在 awk 中变量可以直接使用而不用加 $ 符号。另外这些变量可以使用布尔运算符、比较运算符、算术运算符等。就跟 C 语言一样。
# 具体就是看后面的例子了。
# 2. awk 的处理流程是:
# 2.1 读取第一行,并将第一行的数据填入 $0、$1、$2 等变量中。其中 $0 代表一整行数据,$1 代表分割出来的第一个字段(默认分割符是空格或者 tab)。
# 2.2 根据条件类型的限制,判断是否需要进行后面的动作。
# 2.3 做完所有的动作和条件类型。
# 2.4 如果还有后续的 “行” 数据,则重复 1-3 的步骤,直接数据处理完毕。
# 3. awk 的运算符:
# 比较运算符:> 大于、< 小于、>= 大于等于、<= 小于等于、== 等于、!= 不等于。
# 赋值语句:=。
# 更详细地请看后面的图。
# 4. awk 的内置变量
# 4.1 NF-每一行拥有的字段数。
# 4.2 NR-目前 awk 处理的是第几行数据。
# 4.3 FS-目前的分割字符,默认是空格键。可以重新设置,并且支持正则表达式(扩展)。
# 更详细地请看后面的图。
# 5. 其他关键字
# 5.1 BEGIN 关键字,用来代表一个程序的开始,可以初始化变量,BEGIN 后面的内容只执行一次。
# 5.2 END 关键字,当 awk 程序执行结束之后执行 END 后面 {} 中的动作。
# 6. 内置函数
# 更详细地请看后面的图。
# 提取出账号与登录者的 IP,且账号 IP 之间以 tab 键隔开
$ last -n 5 | awk '{print $1 "\t" $3}'
# 以 : 为分隔符,对 /etc/passwd 文件进行处理,输出 UID(第三字段)小于 10 时的账号(第一字段)及其 UID。
# 需要注意的是,这边需要加上 BEGIN,表示在第一行处理之前就设置好,即预先设置好。假如没有使用 BEGIN 的话,那么第一行的分隔符还是空格或者 tab,可以看上面的流程,也就是从第二行开始分隔符才是 “:”。
$ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}'
# test 的内容如下
Name 1st 2nd 3th
VBird 23000 24000 25000
DMTsai 21000 20000 23000
Bird2 43000 42000 41000
$ cat test | awk 'NR == 1 {printf "%10s %10s %10s %10s %10s\n", $1, $2, $3, $4,"Total"} NR >= 2 {total=$2 + $3 + $4; printf "%10s %10d %10d %10d %10d\n", $1, $2, $3, $4, total}'
Name 1st 2nd 3th Total
VBird 23000 24000 25000 72000
DMTsai 21000 20000 23000 64000
Bird2 43000 42000 41000 126000
# 跟上面效果一样,其中 {} 中可以使用 if,但是条件需要用 () 括起来。同时变量和表达式可以进行计算。
$ cat test | awk '{if (NR==1) printf "%10s %10s %10s %10s %10s\n", $1, $2, $3, $4,"Total"} NR >= 2 {total=$2 + $3 + $4; printf "%10s %10d %10d %10d %10d\n", $1, $2, $3, $4, total}'
# 表达式可以进行如下的算术运算符
awk 'BEGIN {FS=":";one=10;two=109} {if ($3==1000) print one + two}' /etc/passwd
# 可以使用 ||、&&、! 等运算符
awk 'BEGIN {FS=":"} {if ($3==1000 || $4== 1000) print $0}' /etc/passwd
# // 中的内容是正则表达式,/root/ 相当于一个条件,即这一行有满足 root 的字段话,就输出整行。
awk 'BEGIN{FS=":"} /root/{print $0}' /etc/passwd
# 第一个字段是 root 的话,则输出这一行。~ 是一个匹配正则表达式的符号。
awk 'BEGIN{FS=":"} $1~/root/' /etc/passwd
# 这一行中有匹配 root 的话,则输出这一行。
awk 'BEGIN{FS=":"} $0~/root/' /etc/passwd
# 第一个字段不是 root 的话,则输出。! 表示非。
awk 'BEGIN{FS=":"} $1!~/root/' /etc/passwd
# 将第一个字段中含有 root 的替换为 dawnguo,之后再打印整行。其中 OFS 是输出分隔符号。// 中同样是支持正则表达式的。
awk 'BEGIN {FS=":";OFS="--"} gsub(/root/, "dawnguo", $1) {print $0}' /etc/passwd
find
find:递归查找文件
find [PATH] [option] [action]
PATH 可以是多个目录
-mtime n:在 n 天之前的一天之内被更改过的文件(也就是第 n 天之前的那一天),即 4-5 天那一天的文件文件名
-mtime +n:在 n 天之前(不包含 n 天本身)被更改过内容的文件,大于等于 n + 1 前的文件文件名
-mtime -n:在 n 天之内(包 n 天本身)被更改过内容的文件,小于等于 n 天内的文件文件名
-atime
-ctime
-newer file:file 是一个存在的文件,列出比 file 还要新的文件文件名
-uid n:n 是使用者的账号 ID,即 UID 是记录在 /etc/passwd 里面与账号名称对应的数字
-gid n:n 是群组名称的 ID,即 GID
-user name:name 为使用账号名称
-group name:name 为群组名称
-nouser:寻找文件的拥有者不存在 /etc/passwd
-nogroup :寻找文件的拥有群组不存在于 /etc/group
# nouser 和 nogroup 除了自行从网络下载文件时会发生之外。如果你将系统里面的某个账号删除了,但是该账号已经在系统内创建了很多文件时,此时就可以使用 nouser 找出来。
-name filename:搜寻文件名称为 filename 的文件(包括目录,这个是匹配的是文件名而不是路径),-name 默认是大小写字母敏感的,-i 可以忽略大小写。
-regex "[正则表达式]":使用正则表达式的方式查询,但是 -regex 不是匹配文件名而是完整的文件名(包括路径)
-size [+-]SIZE:搜寻比 SIZE 还要大(+)或小(-)的文件。这个 SIZE 的规则有:C-代表 Byte;K-代表 1024 Bytes。比如要找比 50KB 还要大的文件,就是 -size +50K
-type TYPE:搜寻文件的类型为 TYPE 的,类型主要有:一般正规文件(f),设备文件(b、c),目录(d),链接文件(l),socket(s)及 FIFO(p)等属性。
-perm mode:搜寻文件权限“刚好等于” mode 的文件,这个 mode 为类似 chmod 的属性。
-perm -mode:搜寻文件权限“必须要全部囊括 mode”的文件,举例来说,我们必须要搜寻 -rwxr--r-- ,也就是 0744 的文件。那么,一个文件的权限是 -rwsr-xr-x,也就是 4755 的文件也会被列出来。因为 -rwsr-xr-x 已经囊括了 -rwxr--r-- 的属性了。
-perm /mode:搜寻文件权限“包含任一 mode 的权限”的文件,比如 -perm /755,也就是搜寻 -rwxr-xr-x,但一个文件的属性为 -rw------- 也会被列出来,因为有 -rw- 的属性在。
-exec command:command 为其他指令,-exec 后面可再接额外的指令来处理搜寻到的结果
-print:将结果打印到屏幕上,这个动作是默认动作
find / -mtime 0 # 系统上面 24 小时之内有改动过的文件列出,0 代表目前的时间,所以从现在开始到 24 小时前
find / -mtime 3 # 3 天前的 24 小时内
find /home -user dawn # 查看 /home 下面属于 dawn 的文件
find / -nouser # 搜索系统中不属于任何人的文件,这个可以轻易找出那些不太正常的文件。如果有找到不属于系统任何人的文件时,不要慌张,这些是正常的。尤其在以源代码自行编译软件的时候。
find / -name passwd # 找出文件名为 passwd 的文件(这个相当于文件名为 test 的,包括目录和文件)
find / -name '*passwd*' # 找出文件名包含了 passwd 这个关键字的文件(包括目录)
find /run -type s # 找出 /run 目录下,文件类型为 socket 的文件
find / -perm /7000 # 所谓 7000 就是 ---s--s--t,那么只要含有 s 或 t 属性的文件就会列出。-perm -7000 表示要同时含有 ---s--s--t 的所有三个权限的文件。
find /usr/bin /usr/sbin -perm /7000 -exec ls -l {} \;
# 将 find 找到的文件用 ls -l 显示出来。{} 代表的是“由 find 找到的内容”,也就是 find 的结果会被放置到 {} 位置中;-exec 一直到 \; 是关键字,代表 -exec 动作的开始到结束(\;)。
# 需要注意的是,-exec 后面的指令是不支持别名的,比如不能使用 ll
附加:
1. find 还可以利用通配符来寻找文件名,比如上面的 find / -name "*passwd*"
2. find 是去磁盘或者硬盘上查找数据,所以查找数据的时候磁盘操作会很多,所以一般情况下可使用 whereis 和 locate
which
which:寻找可执行文件
which [-a] 文件名
此时会输出该文件名的 alias 信息(如果有的话)和所在的路径。
-a 将所有的由 PATH 目录中可以找到的指令均列出,不止第一个被找到的指令名称。
附加:
which 指令是根据 PATH 这个环境变量所规范的路径,去搜索可执行文件。
whereis
whereis:只找系统中某些特定目录下面的文件而已。
whereis [-bmsu][-B <⽬录>...][-M <⽬录>...][-S <⽬录>...][文件或目录名]
-l 列出 whereis 会去查询的几个主要目录
-b 只找 binary 格式的文件
-m 只找在说明文档 manual 路径下的文件
-s 只找 source 来源文件
-u 查找不在上述三个项目当中的其他特殊文件
-B<⽬录> 只在设置的⽬录下查找⼆进制⽂件
-M<⽬录> 只在设置的⽬录下查找说明⽂件
-S<⽬录> 只在设置的⽬录下查找原始代码⽂件
附:
find 命令是直接搜索磁盘的,而 whereis 是指找几个特定的目录而已,并没有全系统去查,所以 whereis 的速度很快。但是,由于查找的目录有限,因此会存在找不到的情况。要想知道 whereis 查找的是哪些目录下的,可以使用 -l 参数。
locate
locate:利用数据库来搜寻文件名。在完整文件名中(包含路径名称)当中,如果包含了 keyword 的内容,那么就会被显示出来。
locate [options] keyword
-i 忽略大小写的差异
-c 不输出文件名,仅计算找到的文件数量
-l 仅输出几行, -l 5 就表示只输出 5 行
-S 输出 locate 所使用的数据库文件的相关信息,包括该数据库纪录的文件/目录数量
-r 后面可接正则表达式的显示方式,正则表达式是用单引号
-d或--database= 配置 locate 指令使用的数据库
附:
locate 在寻找数据的时候是在已创建的数据库 /var/lib/mlocate 中查找的,而不是去磁盘查找的。数据库的创建默认是在每天执行一次(每个 distribution 都不同),所以当你去搜索你新创建的文件时,locate 会告诉你找不到。
这个时候,就需要更新数据库。使用 updatedb 即可更新数据库,这个指令会去读取 /etc/updatadb.conf 这个配置文件的设置,然后再去硬盘里面进行搜索,最后更新整个数据库文件。
wc
wc:计算文件内容
wc [-lwmc]
-l:仅列出行数;
-w:仅列出多少字(英文单字);
-m:多少字符;
-c:只显示Bytes数;
wc -l test # 计算 test 这个文件的行数
cat test | wc -l # 计算 test 这个文件的行数
附加:
输出的内容分别代表:行树、字数、字符数