网站没有流量,房地产广告设计网站,泰安网签查询2023,森森水族文章目录特殊符号数据流重定向输出重定向输入重定向命令执行的判断根据#xff1a;;、、||管道命令(pipe)选取命令#xff1a;cut、grep排序命令#xff1a;sort、wc、uniq双向重定向#xff1a;tee字符转换命令#xff1a;tr、col、join、paste、expand划分命令…
文章目录特殊符号数据流重定向输出重定向输入重定向命令执行的判断根据;、、||管道命令(pipe)选取命令cut、grep排序命令sort、wc、uniq双向重定向tee字符转换命令tr、col、join、paste、expand划分命令split参数代码xargs关于减号【-】的用途正则表达式是什么grep(擅长查找功能)grep配合基本正则表达式案例grep配合扩展正则表达式案例sed(擅长取行和替换)查找替换删除增加awk(擅长取列)取列取行计算特殊符号
引号类型解析变量$var解析命令$(cmd)解析通配符*典型用途反引号 (优先执行)无自身是命令替换优先执行并替换结果不解析命令结果嵌入和 $(…)相同单引号 不解析不解析不解析原样输出特殊字符双引号 解析解析不解析保留格式并解析变量不加引号解析解析解析自动分词或扩展通配符
[rootubt2404csq ~]# echo 123 whoami $(pwd) csq{01..5}
123 root /root csq{01..5}
[rootubt2404csq ~]# echo 123 whoami $(pwd) csq{01..5}
123 whoami $(pwd) csq{01..5}
[rootubt2404csq ~]# echo 123 whoami $(pwd) csq{01..5}
123 root /root csq01 csq02 csq03 csq04 csq05数据流重定向
数据流重定向是指将命令执行后本应输出到屏幕的数据定向传输到文件、设备或其他位置 什么是数据流重定向 什么是数据流重定向呢这得由命令的执行说起一般来说如果你要执行一个命令通常它会是这样的 数据流名称文件描述符FD默认方向作用说明标准输入0键盘命令从这里读取输入数据标准输出1终端屏幕命令的正常执行结果输出到这里标准错误输出2终端屏幕命令的错误信息如报错输出到这里
我们执行一个命令的时候这个命令可能会由文件读入数据经过处理之后再将数据输出到屏幕上。
输出重定向 基本输输出重定向与 针对 标准输出默认可省略文件描述符 1。
符号语法格式作用说明command file将命令的 stdout 重定向到 file覆盖文件原有内容若文件不存在则创建command file将命令的 stdout 重定向到 file追加到文件末尾若文件不存在则创建
覆盖写入文件
# 将 Hello Linux 覆盖写入 test.txt原内容会丢失
echo Hello Linux test.txt# 查看结果
cat test.txt # 输出Hello Linux追加写入文件
# 将 I love Redirection 追加到 test.txt 末尾
echo I love Redirection test.txt# 查看结果
cat test.txt
# 输出
# Hello Linux
# I love Redirection错误输出重定向2与2 针对 标准错误输出必须显式指定文件描述符 2
符号语法格式作用说明2command 2 error.log将命令的 stderr 重定向到 error.log覆盖原有内容2command 2 error.log将命令的 stderr 重定向到 error.log追加到末尾
捕获错误信息
# 尝试读取不存在的文件错误信息会输出到屏幕
cat no_such_file.txt # 输出cat: no_such_file.txt: No such file or directory# 将错误信息捕获到 error.log
cat no_such_file.txt 2 error.log# 查看错误日志
cat error.log # 输出cat: no_such_file.txt: No such file or directory合并输出stdout stderr 重定向到同一文件 「正常结果」和「错误信息」保存到同一个文件
符号组合语法格式作用说明21command combined.log 21先将 stdout 重定向到文件再将 stderr 「复制」stdout 的方向覆盖command combined.log将 stdout1和 stderr2同时重定向到 combined.log覆盖
将错误和正确的消息都输出到垃圾桶
# 安装软件时屏蔽所有输出不看进度和提示
apt update /dev/null 21输入重定向
输入重定向用于改变命令的「输入来源」从默认的「键盘」改为「文件」或「字符串」 基本输入重定向 针对 标准输入默认可省略文件描述符 0
利用cat命令来建立一个文件的简单流程
[csqlocalhost ~]$ cat catfile
I like Linux
but I dont like English这里按下ctrl d 来退出
[csqlocalhost ~]$ cat catfile
I like Linux
but I dont like Englisht用stdin替换键盘的输入以建立新文件的简单流程
[csqlocalhost ~]$ cat catfile ~/.bashrc
[csqlocalhost ~]$ ll catfile ~/.bashrc
-rw-rw-r--. 1 csq csq 231 Apr 25 15:13 catfile
-rw-r--r--. 1 csq csq 231 Apr 1 2020 /home/csq/.bashrc
# 可以看到两个文件大小一模一样可以自行查看一下内容也是一模一样的基本输入追加重定向 允许你在命令行中直接输入多行文本作为命令的 stdin无需单独创建文件语法为
命令 分隔符
多行文本内容
EOF
# 注意若分隔符单引号如 EOF则多行文本中的变量、命令不会被解析
# 不加引号则会解析生成多行文件
cat poem.txt EOF
床前明月光
疑是地上霜。
举头望明月
低头思故乡。
EOF解析变量
#1.单引号不能解析变量(常用于写入yum.repo文件)
[rootkylin-v10-sp3-csq ~]# home/root
[rootkylin-v10-sp3-csq ~]# cat EOFecho $homeEOF
echo $home
#2.去除单引号即可解析变量(常用于编写脚本可以避免使用大量echo)
[rootkylin-v10-sp3-csq ~]# cat EOF
echo $home
EOF
echo /root命令执行的判断根据;、、||
在某些情况下我想要一次执行很多命令而不想分次执行时该怎么办基本上你有两种选择一个是通过shell脚本去执行一种则是通过下面的介绍来输入多个命令。 cmd ; cmd(不考虑命令相关性的连续命令执行) 在某些时候我们希望可以一次执行多个命令例如关机的时候我希望可以执行两次 sync同步写入磁盘后才shutdown计算机那么可以怎么做呢
[rootlocalhost ~]# sync ; sync ; shutdown -h now在命令与命令中间利用分号【;】开隔开这样一来分号前的命令执行完后就立刻接着执行后面的命令。
那么我如果想在某个目录下面建一个文件也就是说如果该目录存在的话那我才建立文件如果不存在那就不创建文件。也就是说这两个命令彼此之间是由相关性的前一个命令是否成功执行与后一个命令要是否执行有关那就要用或|| $?(命令返回值)与或|| 如同上面谈到的两个命令之间有依赖性而这个依赖性主要判断的地方就在于前面一个命令的执行结果是否正确。判断原理就是【若前面一个命令执行结果正确在Linux下面就会返回一个$?0的值】
命令执行情况说明cmd1 cmd21. 若cmd1 执行完毕且正确执行($?0)则开始执行cmd22. 若cmd1 执行完毕且为错误($?≠0)则cmd2不执行cmd1 || cmd21. 若cmd1 执行完毕且正确执行($?0)则cmd2 不执行2. 若cmd1 执行完毕且为错误($?≠0)则开始执行cmd2
上述cmd1 及 cmd2 都是命令。
# 示例1 使用ls 查看目录/tmp/abc是否存在若存在则用touch 建立/tmp/abc/heh
[rootlocalhost ~]# ls /tmp/abc/ touch /tmp/abc/hehe
ls: cannot access /tmp/abc/: No such file or directory
# ls说无法访问/tmp/abc/: 没有那个文件或目录并没有touch的错误表示touch并没有执行。
[rootlocalhost ~]# mkdir /tmp/abc
[rootlocalhost ~]# ls /tmp/abc/ touch /tmp/abc/hehe
[rootlocalhost ~]# ll /tmp/abc/hehe
-rw-r--r--. 1 root root 0 Apr 25 16:20 /tmp/abc/hehe# 示例2 看到了吧/tmp/abc不存在touch就不会执行若/tmp/abc存在的话
# 那么touch就会开始执行。不过这样非常麻烦能不能自动判断如果没有该目录就自己建立一个
[rootlocalhost ~]# rm -rf /tmp/abc/ # 先删除此目录方便测试
[rootlocalhost ~]# ls /tmp/abc || mkdir /tmp/abc
ls: cannot access /tmp/abc: No such file or directory # ls报错没有/tmp/abc
[rootlocalhost ~]# ll -d /tmp/abc
drwxr-xr-x. 2 root root 6 Apr 25 16:23 /tmp/abc # mkdir创建了# 示例3 如果你再重复执行【ls /tmp/abc || mkdir /tmp/abc】也不会出现重复mkdir的错误
# 这是因为/tmp/abc已经存在了后续的mkdir 就不会执行。
# 如果我想要建立/tmp/abc/hehe这个文件但我不知道/tmp/abc是否存在那该如何是好
[rootlocalhost ~]# ls /tmp/abc || mkdir /tmp/abc touch /tmp/abc/hehe上述案例种尝试建立/tmp/abc/hehe不管/tmp/abc 是否存在。那么案例三应该如何解释由于Linux下面的命令都是由左向右执行所以说上述案例有几种情况来分析一下 (1) 若/tmp/abc 不存在故返回 $?≠0则 (2) 因为 || 遇到非为 0 的$?故开始 mkdir /tmp/abc 由于mkdir /tmp/abc 会成功执行所以返回 $?0 (3) 遇到$?0 故会执行 touch /tmp/abc/hehe 最终hehe被建立 (2) 若/tmp/abc存在故返回 $?0 则(2) 因为|| 遇到0的$?不会执行此时 $?0继续向后传故(3)因为遇到$?0 开始建立 /tmp/abc/hehe 了最终 /tmp/abc/hehe 被建立
整个流程图如下 上面这张图的两股数据种上方的线程为不存在 /tmp/abc 时所进行的命令操作下方的线段则是存在 /tmp/abc 的命令操作。
# 以ls 测试/tmp/csq 是否存在若存在则显示 yes 不存在则显示 no
[rootchenshiren ~]# ls /tmp/csq /dev/null 21 echo yes || echo no
no练习到这里你应该知道了命令是一个接着一个去执行的因此如果真的使用判断那么整个 与 || 的顺序不能搞错。一般来说假设判断式有三个也就是
command1 command2 || command3一般来说 command2 和command3 会使用肯定可以执行的成功的命令。
管道命令(pipe)
有时候我在bash命令执行输出数据的时候有时候数据必须要经过好几个命令处理后才能得到我们想要的结果。这时候我们就可以时候管道命令管道命令使用的是【|】这个符号shift \即可输出。我们来利用管道命令简单的举个例子
假设我们想要知道/etc/下面有多少文件那么可以利用【 ls /etc】 来查看不过因为/etc 下面文件太多了导致输出以后屏幕很多内容此时我们可以通过 less命令的协助
[rootlocalhost ~]# ls /etc/ | less如此一来使用ls命令输出后的内容就能够被less读取并且利用less功能我们就可以前后翻动或者/file 查找文件非常方便。其实这个管道命令【|】仅能处理前一个命令传来的正确信息也就是标准输出信息对于标准错误信息并没有直接处理能力。
管道命令处理流程图如下所示 如上图所示每个管道后面接的第一个数据必定是【命令】而且这个命令必须能够接受标准输入的数据才行这样的命令才可为管道命令如less、more、head、tail 等都是可以接受标准输入的管道命令至于例如 ls、cp、mv等就不是管道命令。因为ls、cp、mv并不会接受来自stdin的数据也就是说管道命令主要有两个比较特殊的地方
管道命令仅会处理标准输出对于标准错误输出会给予忽略管道命令必须要能够接受来自前一个命令的数据成为标准输入继续处理才行。
如果你硬是要让标准错误可以被管道命令所使用的话可以这么做。可以使用数据流重定向让21加入命令中就可以让2 变成1。
选取命令cut、grep
什么是选取命令就是将一段数据经过分析后取出我们所想要的或是经由分析关键词取得我们所想要的那一行。不过要注意的是一般来说选取信息通常是针对【一行一行】来分析的并不是整篇信息分析下面介绍两个很常用的信息选取命令 cut cut翻译成英格利希的意思就是【切】这个命令可以将一段信息的某一段给他【切】出来处理的信息就是以【行】为单位
cut -d 分隔字符 -f 字段
cut -c 字符区间
选项
-d后面接分隔字符与-f一起使用
-f根据-d分隔字符将一段信息划分成为数段用-f取出第几段的意思
-c以字符的单位取出固定字符的区间# 示例1 将PATH变量取出我要找出第五个路径
[rootlocalhost ~]# echo ${PATH}
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin1 2 3 4 5
[rootlocalhost ~]# echo ${PATH} | cut -d : -f 5
/root/bin
# 如同上面数字显示我们是以【:】作为分隔因此会出现/root/bin# 示例2 如果想要列出第3和第5可以这样
[rootlocalhost ~]# echo ${PATH} | cut -d : -f 3,5
/usr/sbin:/root/bin# 示例3 将export输出的信息取得第12字符以后的所有字符
[rootlocalhost ~]# export
declare -x HISTCONTROLignoredups
declare -x HISTSIZE1000
declare -x HOME/root
declare -x HOSTNAMElocalhost.localdomain
declare -x LANGzh_CN.UTF-8
declare -x LESSOPEN||/usr/bin/lesspipe.sh %s
declare -x LOGNAMEroot
.....
.......
...
# 注意看每个数据都是整齐的输出如果我们不想要【declare -x 】时就得这样做
[rootlocalhost ~]# export | cut -c 12-
HISTCONTROLignoredups
HISTSIZE1000
HOME/root
HOSTNAMElocalhost.localdomain
LANGzh_CN.UTF-8
LESSOPEN||/usr/bin/lesspipe.sh %s
LOGNAMEroot
...........
......
...# 示例4 用last将显示的登录者的信息中仅留下使用者的大名
[rootlocalhost ~]# last
root pts/1 192.168.100.1 Wed Apr 26 08:42 still logged in
root pts/0 192.168.100.1 Wed Apr 26 08:42 still logged in
root pts/1 192.168.100.1 Tue Apr 25 15:54 - 18:56 (03:01)
root pts/0 192.168.100.1 Tue Apr 25 15:54 - 18:56 (03:01)
reboot system boot 3.10.0-1160.el7. Tue Apr 25 15:51 - 09:37 (17:45)
.....
.......
...
# last 可以输出【账号/终端/来源/日期时间】的数据并且是排列整齐的。
[rootlocalhost ~]# last | cut -d -f 1
root
root
root
root
reboot
root
root
.....
.......
...
# 由输出的结果我们可以发现第一个空白分隔的栏位代表账号所以使用如上命令
# 但是因为root pts/1 之间空格有好几个并非仅有一个所以如果要找出
# pts1/1 其实不能以 cut -d -f 1,2 输出结果会不是我们想要的grep grep命令将会在下面的内容中介绍
排序命令sort、wc、uniq
很多时候我们都会区计算一次数据里面的相同形式的数据总数举例来说使用last可以查得系统上面有登录主机者的身份。那么我可以针对每个用户查出它们的总登录次数吗此时就要排序与计算之类的命令来辅助下面介绍一下几个好用的排序与统计的命令。 sort sort它可以帮我们进行排序而且可以根据不同的数据形式来排序例如数字与文字的排序就不一样。
sort [-fbMnrtuk] [file 或 stdin]
选项
-f忽略大小写的差异例如A与a视为编码相同
-b忽略最前面的空格字符部分
-M以月份的名字来排序例如JAN、DEC等排序方法
-n使用【纯数字】进行排序(默认是以文字形式来排序的)
-r反向排序
-u就是uniq相同的数据中仅出现一行代表。
-t分隔符号默认是使用[TAB]键来分隔
-k以哪个区间来进行排序的意思。
-h以人类可读的方式排序# 示例1 个人账号都记录在/etc/passwd下请将账号进行排序
[rootlocalhost ~]# cat /etc/passwd | sort
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
csq:x:1000:1000::/home/csq:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
.....
...
# 直接输入sort 默认是以【文字】形式来排序的所以由a开始排序到最后# 示例2 /etc/passwd内容是以【:】分隔的我想以第三栏来排序该如何
[rootlocalhost ~]# cat /etc/passwd | sort -t : -k 3
root:x:0:0:root:/root:/bin/bash
csq:x:1000:1000::/home/csq:/bin/bash
zhw:x:1001:1001::/home/zhw:/bin/bash
zzh:x:1002:1002::/home/zzh:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
....
......
..
# 发现了吗sort默认是以文字形式来排序的如果想要数字排序
# cat /etc/passwd | sort -t : -k 3 -n 这样才行 加上-n来告知sort是以数字来排序# 示例3 利用last将输出的数据仅显示账号并加以排序
[rootlocalhost ~]# last | cut -d -f 1 | sort
# 示例4 查找系统中最大的文件
du -sh /* 2/dev/null | sort -rnk1
#然后一级一级查找直到查到最大的文件uniq 如果我完成了排序我想要将重复的数据仅列出一个显示可以怎么做呢
uniq [-ic]
选项
-i忽略大小写字符的不同
-c进行计数# 示例1 使用last将账号列出仅取出账号栏进行排序后仅取出一位
[rootlocalhost ~]# last | cut -d -f 1 | sort | uniq reboot
root
wtmp# 示例2 如果我还想要知道每个人登录的总次数呢
[rootlocalhost ~]# last | cut -d -f 1 | sort | uniq -c1 7 reboot34 root1 wtmp
# 1.先将所有的数据列出来 2.再将人名独立出来 3.经过排序 4.只显示一个
# 从上述案例得知可以发现reboot出现了7次root登录则有34次大部分都是root在登录
# wtmp与第一行的空白都是last的默认字符两个可以忽略这个命令用来将重复的行删除掉只显示一个举例来说你要知道这个月登录你主机的用户有谁而不在乎它的登录次数那么就可以使用上面的案例。 wc 如果我想知道/etc/man_db.conf 这个文件里面有多少文字多少行多少字符可以利用wc这个命令来完成它可以帮我们计算出信息的整体数据
wc [-lwm]
选项
-l仅列出行
-w仅列出多少字
-m多少字符# 示例1 man_db.conf里面到底有多少行、字数、字符数呢
[rootlocalhost ~]# cat /etc/man_db.conf | wc131 723 5171
# 输出的三个数字中分别代表【行、字数、字符数】# 示例2 使用last可以输出登录者但是last最后两行并非账号内容
# 那么请问我该如何以一行命令串取得登录系统的总人次呢
[rootlocalhost ~]# last |grep [a-zA-z] |grep -v wtmp | grep -v reboot | wc -l
34# 由于last会输出空白行wtmp、reboot等无关账号登录的信息
# 因此利用grep 取出非空白行以及取出上述关键字的那几行在计算行数就好了双向重定向tee
前面我们了解过数据流重定向知道【】会将数据流整个传送给文件或设备因此我们除非去读取该文件或设备否则就无法继续利用整个数据流。那如果我想要将整个数据流处理过程中将某段信息存下来应该怎么做呢利用tee就行 tee会同时将数据流分送到文件与屏幕而输出到屏幕其实是stdout那就可以让下个命令继续处理
tee [-a] file
选项
-a以累加的方式将数据加入file当中# 示例1 将last输出存一份到last.list文件中
[rootlocalhost ~]# last | tee last.list | cut -d -f 1
root
root
root
root
......
...# 示例2 将ls -l /home 的数据存一份到~/homefile同时屏幕也有输出信息
[rootlocalhost ~]# ls -l /home | tee ~/homefile
total 0
drwx------. 2 csq csq 162 Apr 25 14:48 csq
drwx------. 2 zhw zhw 62 Apr 25 09:52 zhw
drwx------. 2 zzh zzh 62 Apr 25 09:52 zzh
# 如果信息很多的话在后面可以加一个【 | less】# 示例3 再ls -l /etc的数据累加到~/homefile中同时屏幕也要输出信息
[rootlocalhost ~]# ls -l /etc/ | tee -a ~/homefile | less
# 是否累加成功可以自行查看字符转换命令tr、col、join、paste、expand tr 可以用来删除一段信息当中的文件或是进行文字信息的替换
tr [-ds] SET1 ....
选项
-d删除信息当中的SET1字符
-s替换掉重复的字符# 示例1 将last输出的信息中所有的小写变成大写字符
[rootlocalhost ~]# last | tr [a-z] [A-Z]
ROOT PTS/1 192.168.100.1 WED APR 26 09:42 STILL LOGGED IN
ROOT PTS/0 192.168.100.1 WED APR 26 09:42 STILL LOGGED IN
.....
...# 示例2 将/etc/passwd 输出信息中将冒号【:】删除
[rootlocalhost ~]# cat /etc/passwd | tr -d :
rootx00root/root/bin/bash
binx11bin/bin/sbin/nologin
daemonx22daemon/sbin/sbin/nologin
admx34adm/var/adm/sbin/nologin
.....
...# 示例3 将/etc/passwd转成dos换行到/root/passwd中再将^M符号删除
[rootlocalhost ~]# cp -rf /etc/passwd ~/passwd unix2dos ~/passwd
unix2dos: converting file /root/passwd to DOS format ...
[rootlocalhost ~]# file ~/passwd
/root/passwd: ASCII text, with CRLF line terminators # 这就是DOS换行
[rootlocalhost ~]# cat ~/passwd | tr -d \r ~/passwd.Linux
[rootlocalhost ~]# ll /etc/passwd ~/passwd*
-rw-r--r--. 1 root root 957 Apr 25 09:52 /etc/passwd
-rw-r--r--. 1 root root 979 Apr 26 15:12 /root/passwd
-rw-r--r--. 1 root root 957 Apr 26 15:12 /root/passwd.Linux
# 处理过后发现文件大小与原本的/etc/passwd就一致了上述案例为什么可以使用\r替换
回车符Carriage Return或者 \r 是一个控制字符它在DOS/Windows系统中作为换行符的一部分存在表示将光标移动到行首。在Linux和Unix系统中换行符只有一个是一个叫做 Line Feed 的字符也就是 \n。 因此当我们在Linux系统中使用cat命令查看一个DOS/Windows系统中的文本文件时会看到很多 ^M 字符这是因为 ^M 是 \r 的可见表示。而在Linux系统中这个字符并不是换行符的一部分因此需要将它替换掉。 tr命令可以用来替换文本中的字符其中 -d 选项表示删除指定的字符因此 tr -d ‘\r’ 表示删除文本中的 \r 字符。所以使用 tr -d ‘\r’ 命令可以将 DOS/Windows 格式的文本文件转换为 Linux 格式。 col col [-xb]
选项
-x将tab键转换成对的空格键# 示例1 利用cat -A 显示出所有的特殊按键最后以col 将[TAB]转成空白
[rootlocalhost ~]# cat -A /etc/man_db.conf
# 执行完这个命令你就看到很多^I的符号那就是tab
[rootlocalhost ~]# cat /etc/man_db.conf | col -x | cat -A |less
# 执行完命令就可以看到所有的[TAB]按键会被替换成为空格键col的用途就是简单的处理[tab]按键替换成空格键。 join join翻译成英格利希的意思就是(参加/加入)它是在处理两个文件之前的数据而且主要是在处理【两个文件当中有相同数据的那一行才将它加在一起的意思。
join [-ti12] file1 file2
选项
-tjoin默认以空格字符分隔数据并且比对【第一个栏位】的数据如果两个文件相同则将两条数据连成一行且第一个栏位放在第一个
-i忽略大小写的差异
-1这个是数字的1代表【第一个文件要用哪个栏位来分析】的意思
-2代表【第二个文件要用哪个栏位来分析】的意思# 示例1 用root身份将/etc/passwd与/etc/shadow相关数据整合成一栏
[rootlocalhost ~]# head -n 3 /etc/passwd /etc/shadow/etc/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 /etc/shadow
root:$6$0x0W5U0lAIGfNePS$fQegjEeiYdvyV7xK7zyhR9jsXzAwkB6XoA6RxpGo0X/uz8uPhblK9frf36sRtpdyNgJY4jZPQplMR1b/Hqgb9/::0:99999:7:::
bin:*:18353:0:99999:7:::
daemon:*:18353:0:99999:7:::
# 由于输出的数据可以发现在两个文件的最左边栏都是相同账号且以:分隔
[rootlocalhost ~]# join -t : /etc/passwd /etc/shadow | head -n 3
root:x:0:0:root:/root:/bin/bash:$6$0x0W5U0lAIGfNePS$fQegjEeiYdvyV7xK7zyhR9jsXzAwkB6XoA6RxpGo0X/uz8uPhblK9frf36sRtpdyNgJY4jZPQplMR1b/Hqgb9/::0:99999:7:::
bin:x:1:1:bin:/bin:/sbin/nologin:*:18353:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin:*:18353:0:99999:7:::
# 通过上面的操作我们可以将两个文件第一栏位相同者整合成一行
# 第二个文件的相同栏位并不会显示(因为已经在最左边的栏位出现了)# 示例2 我们知道/etc/passwd 第四个栏位是GID
# 这个GID记录在/etc/group 当中的第三个栏位请问如何将两个文件整合
[rootlocalhost ~]# head -n 3 /etc/passwd /etc/group/etc/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 /etc/group
root:x:0:
bin:x:1:
daemon:x:2:
# 从上面可以看出确实有相同的部分
[rootlocalhost ~]# join -t : -1 4 /etc/passwd -2 3 /etc/group | head -n 3
0:root:x:0:root:/root:/bin/bash:root:x:
1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:
2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:# 同样的相同的栏位部分移动到了最前面所以第二个文件的内容就每显示paste 这个paste就要比join简单多了。相对于join必须要比对两个文件的数据相关性paste就直接将两行贴在一起且中间以【TAB】键隔开
paste [-d] file1 file2
选项
-d后面可以接分隔字符默认是以【TAB】来分隔
- 如果file部分写错了 -表示来自标准输入的数据的意思# 示例1 用root的身份将/etc/passwd与/etc/shadow同行贴在一起且仅取出前3行
[rootlocalhost ~]# paste /etc/passwd /etc/shadow |head -n 3
root:x:0:0:root:/root:/bin/bash root:$6$0x0W5U0lAIGfNePS$fQegjEeiYdvyV7xK7zyhR9jsXzAwkB6XoA6RxpGo0X/uz8uPhblK9frf36sRtpdyNgJY4jZPQplMR1b/Hqgb9/::0:99999:7:::
bin:x:1:1:bin:/bin:/sbin/nologin bin:*:18353:0:99999:7:::
daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:18353:0:99999:7:::
# 注意同一行间是以【TAB】按键隔开的可以仔细看一下# 示例2 先将/etc/group读出(用cat)然后与上述案例的那两个文件忒在一起且仅取出前3行
[rootlocalhost ~]# cat /etc/group | paste /etc/passwd /etc/shadow - | head -n 3
root:x:0:0:root:/root:/bin/bash root:$6$0x0W5U0lAIGfNePS$fQegjEeiYdvyV7xK7zyhR9jsXzAwkB6XoA6RxpGo0X/uz8uPhblK9frf36sRtpdyNgJY4jZPQplMR1b/Hqgb9/::0:99999:7::: root:x:0:
bin:x:1:1:bin:/bin:/sbin/nologin bin:*:18353:0:99999:7::: bin:x:1:
daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:*:18353:0:99999:7::: daemon:x:2:expand 这个命令就是在将【TAB】按键转成空格键
expand [-t] file
选项
-t后面可接数字一般来说一个TAB按键可以用8个空格键来替换我们也可以自定义一个【TAB】按键代表多少个字符
# 示例1 将/etc/man_db.conf 内行首的MANPATH的字样就取出仅取前三行
[rootlocalhost ~]# grep ^MANPATH /etc/man_db.conf | head -n 3
MANPATH_MAP /bin /usr/share/man
MANPATH_MAP /usr/bin /usr/share/man
MANPATH_MAP /sbin /usr/share/man
# 行首的 ^ 的意思是找出以MANPATH的行# 示例2 上述案例如果我想要将所有的符号都列出来来
[rootlocalhost ~]# grep ^MANPATH /etc/man_db.conf | head -n 3 | cat -A
MANPATH_MAP^I/bin^I^I^I/usr/share/man$
MANPATH_MAP^I/usr/bin^I^I/usr/share/man$
MANPATH_MAP^I/sbin^I^I^I/usr/share/man$
# cat -A 可以将【TAB】键显示为【^I】承接上述案例我将【TAB】按键设置成6个字符的话? 如果你字符长度设置为 9 或 10就又不同了还有个命令unexpand是将空格转成【TAB】命令
我们把上述的案例改一下 在让他转成【TAB】命令
[rootlocalhost ~]# grep ^MANPATH /etc/man_db.conf | head -n 3 | expand -t 8 -| unexpand -t 8 - | cat -A
MANPATH_MAP^I/bin^I^I^I/usr/share/man$
MANPATH_MAP^I/usr/bin^I^I/usr/share/man$
MANPATH_MAP^I/sbin^I^I^I/usr/share/man$
# 就像这样 好像转空格了 又好像没转左右摇摆划分命令split
split命令它可以帮你将一个大文件依据文件大小或行数来划分就可以将大文件划分为小文件了
split [-bl] file PREFIX
选项
-b后面可接欲划分成的文件大小可加单位例如b、k、m等
-l以行数来进行划分
PREFIX代表前缀字符的意思可作为划分文件的前缀文字# 示例1 我的/etc/services 有600多K若想要分成300K一个文件时
[rootlocalhost ~]# cd /tmp/;split -b 300K /etc/services services
[rootlocalhost tmp]# ll -k services*
-rw-r--r--. 1 root root 307200 Apr 26 16:10 servicesaa
-rw-r--r--. 1 root root 307200 Apr 26 16:10 servicesab
-rw-r--r--. 1 root root 55893 Apr 26 16:10 servicesac
# 这个文件名可随意取我们只要写上前缀文字小文件就会以xxxaaaxxxabxxxac等方式来建立小文件# 示例2 如何将上面的三个小文件合成一个文件文件名servicesback
[rootlocalhost tmp]# cat services* servicesback
[rootlocalhost tmp]# ls -l servicesback /etc/services
-rw-r--r--. 1 root root 670293 Jun 7 2013 /etc/services
-rw-r--r--. 1 root root 670293 Apr 26 16:13 servicesback# 示例3 使用ls -al /输出的信息中每十行记录一个文件
[rootlocalhost tmp]# ls -al /etc/ | split -l 10 - lsroot
[rootlocalhost tmp]# wc -l lsroot*0 lsroot10 lsrootaa10 lsrootab10 lsrootac10 lsrootad........
# 重点在这个-号一般来说如果需要stdout或是stdin时但偏偏又没有文件
# 有的只是 - 时那么这个 - 就会被当成 stdin或stdout参数代码xargs
xargs是在做什么以字面的意义来看x是加减乘除的乘号args则是参数的意思所以说这个命令就是在产生某个目录的参数的意思。xargs可以读入stdin的数据并且以空格符或换行符作为识别符将stdin的数据分隔为参数。因为是以空格符作为分隔所以如果有一些文件名或是其他意义的名词内含有空格符的时候xargs可能就会误判用法如下
xargs [-0epn] command
选项
-0如果输入stdin含有特殊字符例如、\、空格等特殊字符时这个-0参数可以将它还原成一般的字符这个参数可以用于特殊状态
-e这个是EOF的意思后面可以接一个字符当xargs分析到这个1字符时就会停止工作
-p在执行每个命令时都会询问使用者的意思
-n后面接次数每次command命令执行时要使用几个参数的意思
当xargs后面没有接任何命令的时候默认是以echo 来进行输出# 示例1 将/etc/passwd内的第一栏取出仅取三行使用id这个命令将每个账号内容显示出来
[rootlocalhost ~]# cut -d : -f 1 /etc/passwd | head -n 3 | xargs -n 1 id
uid0(root) gid0(root) groups0(root)
uid1(bin) gid1(bin) groups1(bin)
uid2(daemon) gid2(daemon) groups2(daemon)
# 通过-n处理一次给予一个参数# 示例2 同上但是执行id时都要询问使用者是否操作
[rootlocalhost ~]# cut -d : -f 1 /etc/passwd | head -n 3 | xargs -p -n 1 id
id root ?...y
uid0(root) gid0(root) groups0(root)
id bin ?...y
uid1(bin) gid1(bin) groups1(bin)
id daemon ?...y
uid2(daemon) gid2(daemon) groups2(daemon)# 示例3 将所有的/etc/passwd内的账号都以id查看但查到sync就结束命令串
[rootlocalhost ~]# cat /etc/passwd | head -n 7
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
[rootlocalhost ~]# cut -d : -f 1 /etc/passwd | xargs -esync -n 1 id
uid0(root) gid0(root) groups0(root)
uid1(bin) gid1(bin) groups1(bin)
uid2(daemon) gid2(daemon) groups2(daemon)
uid3(adm) gid4(adm) groups4(adm)
uid4(lp) gid7(lp) groups7(lp)
# 注意上述案例中那个-esync是连在一起的中间没有空格
# 可以看到我们查看 /etc/passwd sync在第6行当分析到第6行内容时就自动停止了关于减号【-】的用途
管道命令在bash的连续的处理程序中是相当重要的。另外在日志文件的分析中也是相当的重要。在管道命令中常常会使用到一个命令的标准输出(stdout)作为这次的标准输入(stdin)某些命令需要用到文件名(例如 tar)来进行处理时该stdin与stdout可以利用减号【-】来替代举例来说
[rootlocalhost ~]# tar -cvf - /home | tar -xvf - -C /tmp/homeback/上面的例子是说【我将/home里面的文件给他打包但打包的数据不是记录到文件而是传送到stdout经过管道后将tar -cvf - /home 串送给后面的 tar -xvf -】后面的这个【-】则是使用前一个命令的stdout因此我们就不需要文件名了。
正则表达式是什么
简单来说就是通过一些特殊的符号可以让用户完成查找 删除 替换。
正则表达式分两类
基本正则表达式(BRE)对应元字符有【 ^ $ . [ ] *】。扩展正则表达式(ERE) 在BRE基础上增加了 【( ) { } ? | 】等字符 基本正则表达式集合 符号作用^尖角号用于模式的最左侧如 ^csq 就是匹配以csq开头的行$美元符用于模式的最右侧如“csq$”表示以csq结尾的行^$组合符表示空行.匹配任意一个且只有一个字符不能匹配空行\转义字符让特殊含义的符号现出原形如\ . 代表小数点.*匹配前一个字符(连续出现) 0次或1次以上重复0次代表空即匹配所有内容.*组合符匹配所有内容^.*组合符匹配任意多个字符开头的内容.*$组合符匹配以任意多个字符结尾的内容[abc]匹配[ ]集合内的任意一个字符a或b或c可以写成[a-c][^abc]匹配除了^后面的任意字符a或b或c^表示对[abc]的取反扩展正则表达式集合 扩展正则必须用 grep -E 才能生效
字符作用匹配前一个字符1次或多次[ : / ] 匹配括号内的:或者“/”字符1次或多次?匹配前一个字符0次或1次|表示或者同时过滤多个字符()分组过滤被括起来的内容表示一个整体a{n,m}匹配前一个字符最少n次最多M次a{n,}匹配前一个字符最少n次a{n}匹配前一个字符正好n次a{,m}匹配前一个字符最多m次
grep(擅长查找功能)
作用文本搜索工具根据用户指定的“模式过滤条件)”对目标文本逐行进行匹配检查打印匹配到的行
用法: grep [参数选项]... PATTERN [FILE]...
在每个 FILE 或是标准输入中查找 PATTERN。
默认的 PATTERN 是一个基本正则表达式(缩写为 BRE)。
例如: grep -i hello world menu.h main.c参数选项解释说明-v排除匹配结果-n显示匹配行与行号-i不区分大小写-c只统计匹配的行数-E使用扩展正则表达式命令–colorauto为grep过滤结果添加颜色-w只匹配过滤的单词-o只输出匹配的内容-l只打印有匹配的文件的名称
grep配合基本正则表达式案例
测试文件
cat re.txt EOF
I am a student!
I study Linux.I like play computer game
my blog is https://www.chenshiren.xyz
our site is https://www.chenshiren.xyzmy qq is 222333300
not 222333000.good bey see you.
EOF1^以xxxx开头的行 2$以xxxx结尾的行 3^$空行 一般排除空行或者包含井号开头的行
排除空行 排除空行和井号开头的行 4. 任意一个字符 过滤出以.结尾的行 5* 前一个字符出现0次或1次以上 出现/重复/连续出现
过滤出所有包含o的行 正则表达式匹配所有或连续出现的时候贪婪性
过滤以I开头任意内容以game号结尾的行 6[][abc]一个整体包含3个情况匹配a或b或c 过滤a或b或c 过滤大小写字母和数字 过滤出文件中以I或n或g开头的行 过滤出文件中以I或m或n开头的然后结束是数字或字母的 7[^][^abc]不匹配a或b或c 不匹配a或b或c 不匹配小写字母 8过滤出以.结尾的行 匹配.结尾的行[]也可以让.变为普通字符 grep配合扩展正则表达式案例 1| 或者 找出进程关于sshd和rsyslog的进程常见的三种写法 2前一个字符出现1次或1次以上 出现/重复/连续出现
经常与[]搭配实现
匹配出re.txt文件中连续出现的单词 只输出re.txt文件中连续出现的单词 取出re.txt文件中连续出现的单词统计次数取出前5 取出re.txt文件中出现的字母统计次数取出前5 3{}o{n,m}前一个字符o出现至少n次最多m次 表示范围的匹配出现1位数字到3位数字
匹配re.txt文件中数字出现的次数最少1次最多3次 匹配ret.txt文件中数字出现的次数等于3次 使用正则匹配ifconfig的地址 4()一个整体(sed命令中表示反向引用) 找出lscpu命令中CPU缓冲存储器信息4种写法 5? 前一个字符出现0次或1次 对比和* sed(擅长取行和替换)
sed是Stream Editor(字符流编辑器)的缩写简称流编辑器。
sed是操作、过滤和转换文本内容的强大工具
用法: sed [选项]... {sed内置命令符} [输入文件]...sed命令选项说明-n取消默认输出不加上sed把文件内容全输出-r支持扩展正则-i原地编辑(修改文件)-e进行多项(多次)编辑-f指定sed脚本的文件名常用的处理动作 动作解释p打印i在指定行之前插入内容a在指定行之后插入内容c替换指定行的所有内容d删除指定行s查找并替换
查找
类似于grep/egrep,awk //功能本质上就是取行 根据行号取行 #取出第一行
sed -n 1p passwd根据行号范围取行 #范围取行
sed -n 3,5p passwd
#第5行到最后一行
sed -n 5,$p passwd过滤与正则 #过滤passwd文件中包含root的行或oldboy的行
sed -nr /root|csq/p passwd
grep -E root|csq passwd
awk /root|csq/ passwd范围与日志 目标获取一个范围的内容比如2025-01-11到2025-05-01的范围的日志
简易版本
seq 20 | sed -n /2/,/9/p过滤日志中指定时间范围的日志
access.log 过滤 1105分日志到1106分日志
#先检查是否存在
grep 11:05:00 access.log | head
grep 11:06:00 access.log | head
#然后过滤
sed -n /11:05:00/,/11:06:00/p access.log
awk /11:05:00/,/11:06:00/ access.log#secure日志过滤
#12号12点12分00秒到 13号15点15分00秒
grep 12 12:12:00 secure-20161219 | head -1
grep 13 15:15:00 secure-20161219 | head -1
#根据要求格式过滤
sed -n /12 12:12:00/,/13 15:15:00/p secure-20161219
awk /12 12:12:00/,/13 15:15:00/ secure-20161219
#如果不加上日期 过滤输出非常多
sed -n /12:12:00/,/15:15:00/p secure-20161219 | wc -l取出access.log日志中从开头一直到11:30范围日志取出第1列统计次数最多篇的前5
sed -n 1,/2015:11:30:00/p access.log | awk {print $1} | sort | uniq -c | sort -rnk1 | head -5awk NR1,/2015:11:30:00/ access.log | awk {print $1} | sort | uniq -c | sort -rnk1 | head -5awk /2015:11:02:00/,/2015:11:30:00/ access.log | awk {print $1} | sort | uniq -c | sort -rnk1 | head -5排除/删除 文件中空行或注释行grep/sed/awk分别实现 #过滤(取行)三种方法起步
grep -Ev ^($|#) /etc/ssh/sshd_config
sed -r /^(#|$)/d /etc/ssh/sshd_config
awk !/^(#|$)/ /etc/ssh/sshd_config
sed -rn /^(#|$)/!p /etc/ssh/sshd_config替换
sed 的替换命令完整语法为
sed s/原字符串/新字符串/选项 文件名#中间的 / 是默认分隔符
#分隔符可以被任意单个字符替代如 #、、|、_ 等基础替换 #1.先进行替换然后查看效果
sed s#/sbin/nologin#/bin/bash#g passwd#2.加上-i选项修改文件内容注意复制passwd再修改
sed -i s#/sbin/nologin#/bin/bash#g passwd使用正则 #1.给passwd每一行开头加上一个#
#看效果sed s^#g passwd
#修改sed -i s^#g passwd#2.1到5行添加#号
#没加-i只是模拟看效果
sed -r 1,5 s^#g passwd
#包括csq或zhw行添加#
sed -r /csq|zhw/ s^#g passwd修改前备份 修改某个配置文件可以使用如果修改多个文件实现tar打包备份即可
sed -i.bak 1,10 s/^#//g passwd反向引用(后向引用) 核心通过正则把要处理的内容进行分组最后再后面通过\数字方式调用
#原始
root:x:0:0:root:/root:/bin/bash
#目标
/bin/bash:x:0:0:root:/root:root
sed -r s#(.*)(:x.*:)(.*)#\3\2\1#g passwd#原始
[22/Nov/2015:11:02:00 0800]
#目标
[2015/Nov/22:11:02:00 0800]
sed -r s#([0-9])/([a-Z])/([0-9])(.*)#\3/\2/\1\4#g time.log | head删除 按照行位单位进行的 根据行号删除
#删除第三行
seq 10|sed 3d
#删除第三行到第五行
seq 10|sed 3,5d增加
类似追加
#在第五行下面追加内容
seq 10|sed 5a hehe
#在第五行上面追加内容
seq 10|sed 5i hehe
#把第五行的内容替换位指定内容
seq 10|sed 5c heheawk(擅长取列)
awk是一个强大的Linux命令有强大的文本格式化的能力好比将一些文本数据格式化成专业的excel表样式
awk早期在Unix上实现我们用的awk是gawk是GUN awk的意思 awk也是一门编程语言支持条件判断、数组、循环功能等
awk options pattern[action]... filename
# optionsawk可选参数
# pattern 条件类型
# action操作参数 选项说明-F指定分隔字段符-v定义或修改一个awk内部变量-f从脚本文件中读取awk命令内置变量 变量名称代表意义ORS输出当前记录分隔符FS输入字符风隔符默认为空白字符OFS输出字段分隔符默认为空白 字符RS输入记录分隔符输入换行符指定输入时的额换行符NFnumber of Field当前行的字段的个数字段数量NR行号当前处理的文本行的行号FNR各文件分别计数的行号FILENAME当前文件名ARGC命令行参数的个数ARGV数组保存的是命令行所给定的各参数取列 取出/etc/passwd第一列第二列最后一列 awk -F : {print $1,$2,$NF} /etc/passwd运行ip a命令取出网卡ip地址 #输出
[rootkylin-v10-sp3-csq ~]# ip a s ens160
2: ens160: BROADCAST,MULTICAST,UP,LOWER_UP mtu 1500 qdisc mq state UP group default qlen 1000link/ether 00:0c:29:f4:dc:57 brd ff:ff:ff:ff:ff:ffinet 10.0.0.60/24 brd 10.0.0.255 scope global noprefixroute ens160valid_lft forever preferred_lft foreverinet6 fe80::b05d:89d2:5d88:eaa4/64 scope link noprefixroute valid_lft forever preferred_lft forever#可以发现他前面是由空格inet后面是由/24包围的可以选择分割两段
ip a s ens160 | awk NR3| awk -F [ /] {print $3}w命令结果中获取运行时间 #输出
[rootubuntu2204 ~]# w w.txt
[rootubuntu2204 ~]# cat w.txt 20:34:08 up 28 days, 11:49, 1 user, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN IDLE JCPU PCPU WHAT
root pts/1 221.217.117.247 11:14 0.00s 0.12s 0.00s w#可以发现前面是由up 后面是由, 1 user组成
#分成两段前面up 后面想办法匹配, 1 user
awk -F up |, [0-9] user NR1{print $2} w.txt取行
awk NR3’指定行号awk ‘NR3’awk ‘NR3 NR10’ 在/etc/passwd中过滤包含root的行或csq的行 #三种方法
[rootkylin-v10-sp3-csq ~]# grep -E root|csq /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
csq:x:1000:1000::/home/csq:/bin/bash
[rootkylin-v10-sp3-csq ~]# awk /root|csq/ /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
csq:x:1000:1000::/home/csq:/bin/bash
[rootkylin-v10-sp3-csq ~]# sed -nr /csq|root/p passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/bin/bash
csq:x:1000:1000::/home/csq:/bin/bash在/etc/passwd中取指定行 #取/etc/passwd第八行
[rootkylin-v10-sp3-csq ~]# awk NR8 /etc/passwd
halt:x:7:0:halt:/sbin:/sbin/halt
#范围行(第5行到第10行)
[rootkylin-v10-sp3-csq ~]# awk NR5 NR10 /etc/passwd
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
operator:x:11:0:operator:/root:/sbin/nologin计算
awk计算取行取列bc计算 计算内存空闲率 可使用在都在一行内的
[rootkylin-v10-sp3-csq ~]# free -m | awk NR2{print $NF/$2*100%}
50.4292%bc使用结合awk 不在一行内使用awk取放对应变量中然后bc进行计算
cat csq.sh EOF
#!/bin/bash
#dec: 统计内存空闲率#vars
mem_totaltop -bn1 | awk NR4{print $4}
mem_avatop -bn1 | awk NR5{print $(NF-2)}
mem_ava_percentecho scale2;${mem_ava}/${mem_total}*100 | bc -l
#echo
echo 内存空闲率: ${mem_ava_percent}%
EOF
#输出
[rootkylin-v10-sp3-csq ~]# bash csq.sh
内存空闲率: 46.00%