一、连接
💕实例
💕1)如果一个文件由另一个软链接文件而来,则再将这个文件进行硬链接,则硬链接之后的文件还是软连接文件。由于源文件a1本身就是一个软链接文件,所以由它硬链接之后的文件a2还是软链接文件
[root@bz4citestap1014 test]# touch a
[root@bz4citestap1014 test]# ln -s a a1
[root@bz4citestap1014 test]# ll
total 0
-rw-r--r-- 1 root root 0 Jun 5 15:01 a
lrwxrwxrwx 1 root root 1 Jun 5 15:01 a1 -> a
[root@bz4citestap1014 test]# ln a1 a2
[root@bz4citestap1014 test]# ll
total 0
-rw-r--r-- 1 root root 0 Jun 5 15:01 a
lrwxrwxrwx 2 root root 1 Jun 5 15:01 a1 -> a
lrwxrwxrwx 2 root root 1 Jun 5 15:01 a2 -> a
💕2)rm对链接的影响
[root@bz4citestap1014 test]# rm -rf a2
[root@bz4citestap1014 test]# ll
total 0
-rw-r--r-- 1 root root 0 Jun 5 15:01 a
lrwxrwxrwx 1 root root 1 Jun 5 15:01 a1 -> a
[root@bz4citestap1014 test]# ln a a2
[root@bz4citestap1014 test]# ll
total 0
-rw-r--r-- 2 root root 0 Jun 5 15:01 a
lrwxrwxrwx 1 root root 1 Jun 5 15:01 a1 -> a
-rw-r--r-- 2 root root 0 Jun 5 15:01 a2
💕注意:由于源文件a是实文件,则它硬链接之后的文件也是实文件,两者内容双向实时同步。
删除a文件,a1文件失效,a2文件不会失效。
3)cp和mv对链接的影响
💕备份文件不会改变内容
[root@bz4citestap1014 test]# echo "123456" > a
[root@bz4citestap1014 test]# ln a a1 硬链接
[root@bz4citestap1014 test]# cp a a.bak 备份
[root@bz4citestap1014 test]# echo "abc" >> a 插入内容
[root@bz4citestap1014 test]# cat a1
123456
abc
[root@bz4citestap1014 test]# cat a.bak
123456
💕源文件改名,软连接失效,硬链接正常,与改名后的源文件一样
[root@bz4citestap1014 test]# mv a a.bak2
[root@bz4citestap1014 test]# echo "bbbb" >> a.bak2
[root@bz4citestap1014 test]# cat a1
123456
abc
bbbb
💕总结:
💕当源文件cp拷贝到另一个文件时,链接文件跟源文件内容保持一致(跟源文件的备份文件不会保持一致)
💕当源文件mv改为另一个文件时,则链接文件跟源文件mv之后的文件内容保持一致!
💕这个在对日志文件做链接的场景中需要考虑这个情况(考虑日志轮转切割情况下的链接文件内容的一致性问题)
二、💕file命令:打印推测得到的文件类型
常用用法:file -i filename
含义:
打印filename指代的文件的类型和编码格式,没有命令能够确切知道某个文件的编码格式,只能是推测,因此得到的最终文件编码格式不一定是正确的
-i选项:以“mime type”形式打印文件类型和编码格式
三、💕stat命令:打印文件信息
常用用法:stat 文件路径
含义:打印文件的一些详细信息
比如现在有一个"readme"文件,执行"stat readme"命令,可得如图1所示结果。有一个"Desktop"目录,执行"stat Desktop"命令,可得
[root@huanqiu ~]# stat web.xml
File: `web.xml'
Size: 2438 Blocks: 8 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 2764173 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2016-09-08 17:25:51.994707928 +0800
Modify: 2016-09-08 17:25:48.595682668 +0800
Change: 2016-09-08 17:25:48.595682668 +0800
[root@localhost ~]# stat a1
文件:"a1"
大小:12 块:8 IO 块:4096 普通文件
设备:fd00h/64768d Inode:69537082 硬链接:2
权限:(0644/-rw-r--r--) Uid:( 0/ root) Gid:( 0/ root)
环境:unconfined_u:object_r:admin_home_t:s0
最近访问:2021-11-29 14:28:14.772990459 +0800
最近更改:2021-11-29 14:28:10.174990782 +0800
最近改动:2021-11-29 14:28:10.174990782 +0800
创建时间:-
💕输出信息中属性的解释如下:
File:文件名称
Size:文件的大小,这个大小是文件的使用大小
注意,如果是目录文件,该属性值并没有累加统计该目录文件下的子文件的使用大小
Blocks:这个Blocks不是指"inode/block"体系中的block数量。其实指的是某种容量单元的数量。不过可以通过公式“Blocks*单个该种容量单元所含字节数/一个block节点所含字节数”换算得到需要的block节点数量,其中单个该种容量单元所含字节数,可通过"stat --format=%B readme"获得。假如单个该种容量单元的含有字节数为512B,一个block节点含有字节数为4096B,现在Blocks=8,那么block节点数量=1。注意,这个属性极易混淆
IO Block:optimal I/O transfer size hint
"regular file":该值表示文件类型
Device:设备号
Inode:Inode节点号
Links:文件的硬链接计数
Access:文件读取执行权限相关信息
Uid:文件所属用户的信息
Gid:文件所属组的信息
Access:atime
Modify:mtime
Change:ctime
Birth:文件创建时间,一般情况下不存在该属性值
四、💕basename命令:去除路径前缀和后缀
常用用法:basename NAME [SUFFIX]
含义:给定一个文件名路径,除去前导的目录名,如果指定了SUFFIX,那么也除去SUFFIX指定的后缀,把最终结果打印出来
比如
basename include/stdio.h .h
除去前导的目录名"include/",得到stdio.h
指定SUFFIX=.h,那么除去.h后缀,最后得到stdio
打印stdio
五、💕dirname命令:获取路径的目录部分
常用用法:dirname NAME
含义:
给定一个文件名路径,除去最后一部分名称内容,接着除去冗余的后导"/",打印最终结果;
如果文件名路径中不包含"/",那么最后打印"."
扩展:
截取目录的方法,有以下两种:
1)dirname命令:用于取给定路径的目录部分。这个命令很少直接在shell命令行中使用,一般把它用在shell脚本中,用于取得脚本文件所在目录,
然后将当前目录切换过去。
其实就是取所给路径的倒数第二级及其之前的路径部分,如下:
[root@jenkins-server Shell]# dirname main/protected/xqsjmob/themes/tpl2/common/page_statistics.tpl
main/protected/xqsjmob/themes/tpl2/common
[root@jenkins-server Shell]# dirname /usr/local/tomcat7/webapps/jenkins/scripts/Shell
/usr/local/tomcat7/webapps/jenkins/scripts
[root@jenkins-server Shell]# dirname FF_Online.sh #取的结果既是当前路径目录下
.
2)可以用${pathname%/*}截取掉pathname后面的文件部分。
下面比较下这两种方法的效果:即dirname取的是倒数第二级及其以上级的路径,而${pathname%/*}取的是"删除最后一个/符号后的路径部分"
[root@jenkins-server Shell]# pathname=/usr/bin/sort; echo $(dirname $pathname) ${pathname%/*}
/usr/bin /usr/bin
You have new mail in /var/spool/mail/root
[root@jenkins-server Shell]# pathname=/usr/bin/sort/; echo $(dirname $pathname) ${pathname%/*}
/usr/bin /usr/bin/sort
[root@jenkins-server Shell]# pathname=/usr/; echo $(dirname $pathname) ${pathname%/*}
/ /usr
[root@jenkins-server Shell]# pathname=/usr; echo $(dirname $pathname) ${pathname%/*}
六、💕du命令:查看文件大小
一、常用用法
du -sh [--apparent-size] 文件路径(文件可以是目录,也可以是一般文件)
二、含义与选项
2.1、含义
当文件为一般文件时,估算该一般文件的大小;当文件为目录时,估算"该目录自身的大小+目录下所有子文件(递归进行)的大小"。
2.2、选项表示的意思
"-s":当du命令的操作对象是一个目录时,不打印该目录下子文件的大小统计情况,只打印目录总体的大小统计情况
"-h":以人类可读形式展示文件大小
"--apparent-size":当不加该选项时,"文件大小"是指文件的"占用大小";当加了该选项后,"文件大小"是指文件的"使用大小"。
三、实验
现在有一个"test1"目录,其下有一个"test2"目录,"test2"目录下有一个"test3"目录,在"test3"目录下有一个"test4.txt"文件,如下所示:
[root@redis-new01 ~]# ll -d test1
drwxr-xr-x 3 root root 4096 Oct 27 21:17 test1
[root@redis-new01 ~]# ls test1/
test2
[root@redis-new01 ~]# ls test1/test2/
test3
[root@redis-new01 ~]# ls test1/test2/test3/
test4.txt
"test1"目录对应1个block节点(大小为4096B),"test2"目录也对应1个block节点(大小为4096B),"test3"目录也对应1个block节点(大小为4096B),
"test4.txt"文件也对应1个block节点(大小为4096B),而"test4.txt"这个一般文件对应的block节点中实际使用的空间大小为12B。
1)如下命令
[root@redis-new01 ~]# du -h test1
8.0K test1/test2/test3
12K test1/test2
16K test1
这是因为:
16K=test1自身的4K+test2自身的4K+test3自身的4K+test4.txt的4K。
2)如下命令
[root@redis-new01 ~]# du -sh test1
16K test1
这是因为:
16K=test1自身的4K+test2自身的4K+test3自身的4K+test4.txt的4K,并且只显示最终的test1目录的总体大小。
3)如下命令
[root@redis-new01 ~]# du -sh --apparent-size test1
13K test1
这是因为:
根据右侧值向上取整得到13K=12K+12B=test1自身的4K+test2自身的4K+test3自身的4K+test4.txt的12B,并且只显示最终的test1目录的总体大小。
七、💕cat、more、less、tail、head命令
💕cat 是一个文本文件(查看)和(连接)工具,通常与more搭配使用,与more不同的是cat可以合并文件。查看一个文件的内容,用cat比较简单,就是cat后面直接接文件名。
💕cat [选项] [文件]...
选项
-b, --number-nonblank 对非空输出行编号
-n, --number 对输出的所有行编号
💕cat 查看文件内容实例:
[root@kevin ~]# cat /etc/profile //查看/etc/目录下的profile文件内容;
[root@kevin ~]# cat -b /etc/fstab //查看/etc/目录下的fstab内容,并且对非空白行进行编号,行号从1开始;
[root@kevin ~]# cat -n /etc/profile //对/etc目录中的profile的所有的行(包括空白行)进行编号输出显示;
💕cat 加参数-n 和nl工具差不多,文件内容输出的同时,都会在每行前面加上行号
[root@kevin ~]# cat -n /etc/profile
[root@kevin ~]# nl /etc/profile
💕cat 可以同时显示多个文件的内容,比如我们可以在一个cat命令上同时显示两个文件的内容;
[root@kevin ~]# cat /etc/fstab /etc/profile
💕cat 对于内容极大的文件来说,可以通过管道|传送到more 工具,然后一页一页的查看;
[root@kevin ~]# cat /etc/fstab /etc/profile | more
💕cat 的创建、连接文件功能实例:
cat 有创建文件的功能,创建文件后,要以EOF或STOP结束;
[root@kevin ~]# cat > kevin.txt<< EOF
> 我来测试 cat 创建文件,并且为文件输入内容;
> 北京是个好地方;
> EOF
💕cat 还有向已存在的文件追加内容的功能;
[root@kevin ~]# cat >> grace.txt << EOF
> 我来测试cat向文档追加内容的功能;
> OK?
> OK~
> 北京你好
> EOF
💕cat 连接多个文件的内容并且输出到一个新文件中;
通过cat 把sir01.txt、sir02.txt及sir03.txt 三个文件连接在一起(也就是说把这三个文件的内容都接在一起)并输出到一个新的文件sir04.txt 中。
注意:
其原理是把三个文件的内容连接起来,然后创建sir04.txt文件,并且把几个文件的内容同时写入sir04.txt中。特别值得一提的是,如果您输入到一个已经存在的sir04.txt 文件,会把sir04.txt内容清空。
[root@kevin ~]# cat sir01.txt sir02.txt sir03.txt > sir04.txt
[root@kevin ~]# more sir04.txt
123456
i am testing
56789
BeiNan Tested
09876
grace.org testing
💕cat 把一个或多个已存在的文件内容,追加到一个已存在的文件中
[root@kevin ~]# cat sir00.txt
grace.org forever
[root@kevin ~]# cat sir01.txt sir02.txt sir03.txt >> sir00.txt
[root@kevin ~]# cat sir00.txt
grace.org forever
123456
i am testing
56789
BeiNan Tested
09876
grace.org testing
cat filename.txt | awk 'NR%2==1' 删除filename.txt文件中的所有偶数行
======================================================
💕more 是我们最常用的工具之一,最常用的就是显示输出的内容,然后根据窗口的大小进行分页显示,然后还能提示文件的百分比;
参数如下:
+num 从第num行开始显示;
-num 定义屏幕大小,为num行;
+/pattern 从pattern 前两行开始显示;
-c 从顶部清屏然后显示;
-d 提示Press space to continue, 'q' to quit.(按空格键继续,按q键退出),禁用响铃功能;
-l 忽略Ctrl+l (换页)字符;
-p 通过清除窗口而不是滚屏来对文件进行换页。和-c参数有点相似;
-s 把连续的多个空行显示为一行;
-u 把文件内容中的下划线去掉退出more的动作指令是q
💕more 的参数应用举例:
[root@kevin ~]# more -dc /etc/profile //显示提示,并从终端或控制台顶部显示;
[root@kevin ~]# more +4 /etc/profile //从profile的第4行开始显示;
[root@kevin ~]# more -4 /etc/profile //每屏显示4行;
[root@kevin ~]# more +/MAIL /etc/profile //从profile中的第一个MAIL单词的前两行开始显示;
💕more 的动作指令:
ctrl+f(或空格键) 是向下显示一屏
ctrl+b是返回上一屏
空格键 向下滚动一屏;
= 输出当前行的行号;
:f 输出文件名和当前行的行号;
v 调用vi编辑器;
! 命令 调用Shell,并执行命令;
q 退出more当我们查看某一文件时,想调用vi来编辑它,不要忘记了v动作指令,这是比较方便的;
💕其它命令通过管道和more结合的运用例子:
比如我们列一个目录下的文件,由于内容太多,我们应该学会用more来分页显示。这得和管道 | 结合起来,比如:
[root@kevin ~]# ls -l /etc |more
=======================================================
💕less 查看文件内容 工具
less 工具是对文件或其它输出进行分页显示的工具
💕常用参数
-c 从顶部(从上到下)刷新屏幕,并显示文件内容。而不是通过底部滚动完成刷新;
-f 强制打开文件,二进制文件显示时,不提示警告;
-i 搜索时忽略大小写;除非搜索串中包含大写字母;
-I 搜索时忽略大小写,除非搜索串中包含小写字母;
-m 显示读取文件的百分比;
-M 显法读取文件的百分比、行号及总行数;
-N 在每行前输出行号;
-p pattern 搜索pattern;比如在/etc/profile搜索单词MAIL,就用 less -p MAIL /etc/profile
-s 把连续多个空白行作为一个空白行显示;
-Q 在终端下不响铃;
比如:我们在显示/etc/profile的内容时,让其显示行号;
[root@kevin ~]# less -N /etc/profile
💕less的动作:
回车键 向下移动一行;
y 向上移动一行;
空格键 向下滚动一屏;
b 向上滚动一屏;
d 向下滚动半屏;
h less的帮助;
u 向上洋动半屏;
w 可以指定显示哪行开始显示,是从指定数字的下一行显示;比如指定的是6,那就从第7行显示;
g 跳到第一行;
G 跳到最后一行;
p n% 跳到n%,比如 10%,也就是说比整个文件内容的10%处开始显示;
/pattern 搜索pattern ,比如 /MAIL表示在文件中搜索MAIL单词;
v 调用vi编辑器;
q 退出less
!command 调用SHELL,可以运行命令;比如!ls 显示当前列当前目录下的所有文件;
==========================================================
💕head 工具,显示文件内容的前几行
用法;head -n 行数值 文件名;
比如我们显示/etc/profile的前10行内容,应该是:
[root@kevin ~]# head -n 10 /etc/profile
=========================================================
💕tail 工具,显示文件内容的最后几行
-n 最后多少行,默认显示后10行
-f 文件最新追加的行
-n +数字 从第几行到最后一行
查看第10行到20行
head -20 a.txt | tail -11
比如我们显示/etc/profile的最后5行内容,应该是:
[root@kevin ~]# tail -n 5 /etc/profile
=========================================================
💕tac:从最后一行显示
八、💕cut
💕cut是一个选取命令,就是将一段数据经过分析,取出我们想要的。一般来说,选取信息通常是针对“行”来进行分析的,并不是整篇信息分析的。
💕其语法格式为:
cut [-bn] [file] 或 cut [-c] [file] 或 cut [-df] [file]
💕使用说明
cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。
如果不指定 File 参数,cut 命令将读取标准输入。必须指定 -b、-c 或 -f 标志之一。
💕主要参数
-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位进行分割。
-d :自定义分隔符,默认为制表符。
-f :与-d一起使用,指定显示哪个区域。
-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的<br />范围之内,该字符将被写出;否则,该字符将被排除。
💕cut命令主要是接受三个定位方法:
第一,字节(bytes),用选项-b
第二,字符(characters),用选项-c
第三,域(fields),用选项-f
=========================================
💕cut在取列内容的时候和awk相识
awk -F"" '{print $n}' 以-F后的引号内的内容为列的分隔符,打印第n列
cut -d"" -fn 以-d后的引号内的内容为列的分隔符,打印第n列
比如打印a.txt文件中以空格为列的分隔符,打印第5行
awk -F" " '{print $5}' a.txt 当以空格为分隔符的时候,-F" " 可以省去
cut -d" " -f5 a.txt
💕举例说明:
[root@localhost ~]# cat a
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
[root@localhost ~]# awk -F" " '{print $5}' a
5
10
15
20
[root@localhost ~]# cut -d" " -f5 a
5
10
15
20
=========================================
💕以“字节”定位
[root@kevin ~]# who
rocrocket :0 2009-01-08 11:07
rocrocket pts/0 2009-01-08 11:23 (:0.0)
rocrocket pts/1 2009-01-08 14:15 (:0.0)
💕提取每一行的第3个字节
[root@kevin ~]# who|cut -b 3
c
c
c
💕提取第3,第4、第5和第8个字节:-b支持形如3-5的写法,而且多个定位之间用逗号隔开。
[root@kevin ~]# who|cut -b 3-5,8
croe
croe
croe
💕但有一点要注意,cut命令如果使用了-b选项,那么执行此命令时,cut会先把-b后面所有的定位进行从小到大排序,然后再提取。不能颠倒定位的顺序。
[root@kevin ~]# who|cut -b 8,3-5
croe
croe
croe
💕小技巧
[root@kevin ~]# who
rocrocket :0 2009-01-08 11:07
rocrocket pts/0 2009-01-08 11:23 (:0.0)
rocrocket pts/1 2009-01-08 14:15 (:0.0)
[root@kevin ~]# who|cut -b -3
roc
roc
roc
[root@kevin ~]# who|cut -b 3-
crocket :0 2009-01-08 11:07
crocket pts/0 2009-01-08 11:23 (:0.0)
crocket pts/1 2009-01-08 14:15 (:0.0)
💕-3表示从第一个字节到第三个字节,而3-表示从第三个字节到行尾。如果你细心,你可以看到这两种情况下,都包括了第三个字节“c”。
如果我执行who|cut -b -3,3-,你觉得会如何呢?答案是输出整行,不会出现连续两个重叠的c的。看:
[root@kevin ~]# who|cut -b -3,3-
rocrocket :0 2009-01-08 11:07
rocrocket pts/0 2009-01-08 11:23 (:0.0)
rocrocket pts/1 2009-01-08 14:15 (:0.0)
💕-b和-c区别:提取中文
用-c则会以字符为单位,输出正常;
而-b只会傻傻的以字节(8位二进制位)来计算,输出就是乱码。
💕当遇到多字节字符时,可以使用-n选项,-n用于告诉cut不要将多字节字符拆开。例子如下:
[root@kevin ~]# cat cut_ch.txt |cut -b 2
[root@kevin ~]# cat cut_ch.txt |cut -nb 2
星
星
星
星
💕-b和-c只能在固定格式的文档中提取信息,而对于非固定格式的信息则束手无策。这时候“域”就派上用场了。cut命令提供了这样的提取方式,具体的说就是设置“间隔符”,再设置“提取第几个域”,就OK了!
以/etc/passwd的前五行内容为例:
[root@kevin ~]# cat /etc/passwd|head -n 5
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
[root@kevin ~]# cat /etc/passwd|head -n 5|cut -d : -f 1
root
bin
daemon
adm
lp
💕用-d来设置间隔符为冒号,然后用-f来设置我要取的是第一个域,再按回车,所有的用户名就都列出来了!在设定-f时,也可以使用例如3-5或者4-类似的格式:
[root@kevin ~]# cat /etc/passwd|head -n 5|cut -d : -f 1,3-5
root:0:0:root
bin:1:1:bin
daemon:2:2:daemon
adm:3:4:adm
lp:4:7:lp
[root@kevin ~]# cat /etc/passwd|head -n 5|cut -d : -f -2 1到2
root:x
bin:x
daemon:x
adm:x
lp:x
💕空格和制表符
如果是制表符(TAB),那么会显示为\t符号,如果是空格,就会原样显示。通过此方法即可以判断制表符和空格了。
[root@kevin ~]# cat tab_space.txt
this is tab finish.
this is several space finish.
[root@kevin ~]# sed -n l tab_space.txt
this is tab\tfinish.$
this is several space finish.$
💕cut的-d选项的默认间隔符就是制表符,所以当你就是要使用制表符的时候,完全就可以省略-d选项,而直接用-f来取域就可以了。
💕注意:只能在-d后面设置一个空格,不许设置多个空格,因为cut只允许间隔符是一个字符。
九、💕tr
可以把tr看作为一个简化的sed工具,tr表示为:translate。tr命令主要用于实现以下两个功能
1)替换操作的字符串转换。
2)删除操作的字符串转换,可以很容易的删除一些控制字符或者是空行。
一,💕命令格式
tr [option] ["string1"] ["string2"] < file
常用的选项有:
默认选项。就是没有任何选项的时候,tr默认为替换操作,就是将string1在文件中出现的字符替换为string2中的字符,这里要注意的是替换关系。
-c选项,用string1中字符的补集替换string1,这里的字符集为ASCII。
-d选项,删除文件中所有在string1中出现的字符。
-s选项,删除文件中重复并且在string1中出现的字符,只保留一个。
-c选项在使用时,只是将string1替换为现在的补集
[root@kevin ~]# echo "hello world,root,2012" | tr -c "0-9" "*"
*****************2012*
可以看出,我们使用0-9,添加-c选项后,会把0-9替换为其补集,这时补集自然不包含0-9,而包含很多其它的字符,接下来就把所有的其它字符都替换成*号,但不包含数字。
如果只需要替换数字的话:
[root@kevin ~]# echo "hello world,root,2012" | tr "0-9" "*"
hello world,root,****
二,💕字符串的取值范围
指定string或string2的内容时,只能使用单字符或字符串范围或列表。
[a-z] a-z内的字符组成的字符串。
[A-Z] A-Z内的字符组成的字符串。
[0-9] 数字串。
\octal 一个三位的八进制数,对应有效的ASCII字符。
[O*n] 表示字符O重复出现指定次数n。因此[O*2]匹配OO的字符串。
三,💕控制字符的不同表达方式
速记符 含义 八进制方式
\a Ctrl-G 铃声\007
\b Ctrl-H 退格符\010
\f Ctrl-L 走行换页\014
\n Ctrl-J 新行\012
\r Ctrl-M 回车\015
\t Ctrl-I tab键\011
\v Ctrl-X \030 注意这些控制字符,如果想在linux下输入,如我们可能需要输入^M这种字符,只需ctrl+V+M同时按下即可。
四,💕字符替换
这是tr的默认操作,先看下面的命令和输出
[root@kevin ~]# echo "hello world" | tr "a-z" "A-Z"
HELLO WORLD
[root@kevin ~]# echo "hello world" | tr "a-l" "A-Z"
HELLo worLD
[root@kevin ~]# echo "hello world" | tr "a-z" "A-H"
HEHHH HHHHD
第一行输出就是将小写换成大写。
第二行输出将小写中的a-l分别换成A-L,而将小写中的l以后的字符都不替换。
第三行输出将小写中的a-h换成A-H,而h以后的字符都换成H,因为后者的替换空间没有前面的字符空间大,所以就重复后面的H,
相当于后面的字符是A-HHH......HHHHH。
如果我们想要进行大小写转换,可以按下面的输入:
tr "a-z" "A-Z" < inputfile
五,💕去除重复字符
这个时候,所用的选项是-s选项,如:
[root@kevin ~]# echo "hello world,root" | tr -s "ao"
hello world,rot
[root@kevin ~]# echo "hello world,root" | tr -s "lo"
helo world,rot
[root@kevin ~]# echo "hello world,root" | tr -s "a-z"
helo world,rot
[root@kevin ~]# echo "hello world,root" | tr -s "0-9"
hello world,root
第一行表示将输入字符串中的包含在"ao"字符集中的重复字符去掉,只留一个。因为"hello world,root",只有o满足条件,所以将root变成rot,把中间的两个o变成一个。
第二行将hello和root两个字符都压缩了。
第三行表示将a-z中的除复字符都去掉。
第三行表示将字符串中的重复的且重复字符在0-9字符集中的字符去掉,这里没有。
如果我们想要去掉空行,可以这样操作:
tr -s "\n" < inputfile 或者 tr -s "\012" <inputfile // 这两个是一样的。
就是将重复的换行符去掉,只留一个。
六,💕删除字符
-d选项和-s选项类似,只不过-d选项会删除所有出现的字符。
[root@kevin ~]# echo "hello world,root" | tr -d "a-h"
llo worl,root
[root@kevin ~]# echo "hello world,root,2012" | tr -d "a-z"
,,2012
[root@kevin ~]# echo "hello world,root,2012" | tr -d "0-9"
十、sort/uniq/cut/wc命令
💕sort 命令对 File 参数指定的文件中的行排序,并将结果写到标准输出。如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序。
sort语法
sort [-fbMnrtuk] [file or stdin]
选项与参数:
-f :忽略大小写的差异,例如 A 与 a 视为编码相同;
-b :忽略最前面的空格符部分;
-M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;
-n :使用『纯数字』进行排序(默认是以文字型态来排序的);
-r :反向排序;
-u :就是 uniq ,相同的数据中,仅出现一行代表;
-t :分隔符,默认是用 [tab] 键来分隔;
-k :以那个区间 (field) 来进行排序的意思
对/etc/passwd 的账号进行排序
[root@kevin ~]# cat /etc/passwd | sort
adm:x:3:4:adm:/var/adm:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
sort 是默认以第一个数据来排序,而且默认是以字符串形式来排序,所以由字母 a 开始升序排序。
/etc/passwd 内容是以 : 来分隔的,我想以第三栏来排序,该如何
[root@kevin ~]# cat /etc/passwd | sort -t ':' -k 3
root:x:0:0:root:/root:/bin/bash
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
默认是以字符串来排序的,如果想要使用数字排序:
[root@kevin ~]# cat /etc/passwd | sort -t ':' -k 3n
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
默认是升序排序,如果要倒序排序,如下
[root@kevin ~]# cat /etc/passwd | sort -t ':' -k 3nr
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
ntp:x:106:113::/home/ntp:/bin/false
messagebus:x:105:109::/var/run/dbus:/bin/false
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
如果要对/etc/passwd,先以第六个域的第2个字符到第4个字符进行正向排序,再基于第一个域进行反向排序。
[root@kevin ~]# cat /etc/passwd | sort -t':' -k 6.2,6.4 -k 1r
sync:x:4:65534:sync:/bin:/bin/sync
proxy:x:13:13:proxy:/bin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
查看/etc/passwd有多少个shell:对/etc/passwd的第七个域进行排序,然后去重:
[root@kevin ~]# cat /etc/passwd | sort -t':' -k 7 -u
root:x:0:0:root:/root:/bin/bash
syslog:x:101:102::/home/syslog:/bin/false
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin
sort file1 file2 排序两个文件的内容
sort file1 file2 | uniq 取出两个文件的并集(重复的行只保留一份)
sort file1 file2 | uniq -u 删除交集,留下其他的行
sort file1 file2 | uniq -d 取出两个文件的交集(只留下同时存在于两个文件中的文件)
==================================================================
💕uniq命令可以去除排序过的文件中的重复行,因此uniq经常和sort合用。也就是说,为了使uniq起作用,所有的重复行必须是相邻的。
uniq语法
uniq [-icu]
选项与参数:
-i :忽略大小写字符的不同;
-c :进行计数
-u :只显示唯一的行
[root@kevin ~]# cat testfile
hello
world
friend
hello
world
hello
直接删除未经排序的文件,将会发现没有任何行被删除
[root@kevin ~]# uniq testfile
hello
world
friend
hello
world
hello
排序文件,默认是去重
[root@kevin ~]# cat words | sort |uniq
friend
hello
world
排序之后删除了重复行,同时在行首位置输出该行重复的次数
[root@kevin ~]# sort testfile | uniq -c
1 friend
3 hello
2 world
仅显示存在重复的行,并在行首显示该行重复的次数
[root@kevin ~]# sort testfile | uniq -dc
3 hello
2 world
仅显示不重复的行
[root@kevin ~]# sort testfile | uniq -u
friend
===============================================
💕sort|uniq 排序去重
💕sort|uniq -c|srot -rn 排序去重,并降序
💕sort|uniq -c 打印重复的行数
💕sort|uniq -d 打印交集部分
💕sort|uniq -u 打印交集以外的部分
💕sort -rn 降序
💕sort -k3rn 按照第三列降序
==============================================
[root@kevin ~]# cat a.txt
sdfsdf
123
123
1234
123
dasdfsd
sdfsdf
asfd34234
[root@kevin ~]# cat a.txt |sort|uniq
123
1234
asfd34234
dasdfsd
sdfsdf
[root@kevin ~]# cat a.txt |sort|uniq -c
3 123
1 1234
1 asfd34234
1 dasdfsd
2 sdfsdf
[root@kevin ~]# cat a.txt |sort|uniq -d
123
sdfsdf
[root@kevin ~]# cat a.txt |sort|uniq -u
1234
asfd34234
dasdfsd
[root@kevin ~]# cat a.txt
sdfsdf
123
123
1234
123
dasdfsd
sdfsdf
asfd34234
[root@kevin ~]# cat b.txt
sdf
123
err
2345
123
gggg
[root@kevin ~]# cat a.txt b.txt |sort|uniq
123
1234
2345
asfd34234
dasdfsd
err
gggg
sdf
sdfsdf
[root@kevin ~]# cat a.txt b.txt |sort|uniq -c
5 123
1 1234
1 2345
1 asfd34234
1 dasdfsd
1 err
1 gggg
1 sdf
2 sdfsdf
[root@kevin ~]# cat a.txt b.txt |sort|uniq -d
123
sdfsdf
[root@kevin ~]# cat a.txt b.txt |sort|uniq -u
1234
2345
asfd34234
dasdfsd
err
gggg
sdf
=======================================================
💕cut命令可以从一个文本文件或者文本流中提取文本列。
cut语法
cut -d'分隔字符' -f fields <==用于有特定分隔字符
cut -c 字符区间 <==用于排列整齐的信息
选项与参数:
-d :后面接分隔字符。与 -f 一起使用;
-f :依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思;
-c :以字符 (characters) 的单位取出固定字符区间;
PATH 变量如下
[root@kevin ~]# echo $PATH
/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games
# 1 | 2 | 3 | 4 | 5 | 6 | 7
将 PATH 变量取出,我要找出第五个路径。
[root@kevin ~]# echo $PATH | cut -d ':' -f 5
/usr/local/bin
将 PATH 变量取出,我要找出第三和第五个路径。
[root@kevin ~]# echo $PATH | cut -d ':' -f 3,5
/sbin:/usr/local/bin
将 PATH 变量取出,我要找出第三到最后一个路径。
[root@kevin ~]# echo $PATH | cut -d ':' -f 3-
/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games
将PATH 变量取出,我要找出第一到第三个路径。
[root@kevin ~]# echo $PATH | cut -d ':' -f 1-3
/bin:/usr/bin:/sbin:
将PATH 变量取出,我要找出第一到第三,还有第五个路径。
[root@kevin ~]# echo $PATH | cut -d ':' -f 1-3,5
/bin:/usr/bin:/sbin:/usr/local/bin
实用例子:只显示/etc/passwd的用户和shell
[root@kevin ~]# cat /etc/passwd | cut -d ':' -f 1,7
root:/bin/bash
daemon:/bin/sh
bin:/bin/sh
====================================================
💕wc统计文件里面有多少单词,多少行,多少字符。
wc语法
[root@kevin ~]# wc [-lwm]
选项与参数:
-l :仅列出行;
-w :仅列出多少字(英文单字);
-m :多少字符;
默认使用wc统计/etc/passwd
[root@kevin ~]# wc /etc/passwd
40 45 1719 /etc/passwd
40是行数,45是单词数,1719是字节数
wc的命令比较简单使用,每个参数使用如下:
[root@kevin ~]# wc -l /etc/passwd #统计行数,在对记录数时,很常用
40 /etc/passwd #表示系统有40个账户
[root@kevin ~]# wc -w /etc/passwd #统计单词出现次数
45 /etc/passwd
[root@kevin ~]# wc -m /etc/passwd #统计文件的字节数
💕十一、split命令:切分文件
split命令用于将一个文件分割成数个。
该指令将大文件分割成较小的文件,在默认情况下将按照每1000行切割成一个小文件。
语法
split [--help][--version][-<行数>][-b <字节>][-C <字节>][-l <行数>][要切割的文件][输出文件名]
参数说明:
-<行数> : 指定每多少行切成一个小文件.如split -3 a.txt
-b<字节> : 指定每多少字节切成一个小文件
-l, --lines=NUMBER:对file进行切分,每个文件有NUMBER行。
--help : 在线帮助
--version : 显示版本信息
-C<字节> : 与参数"-b"相似,但是在切 割时将尽量维持每行的完整性
[输出文件名] : 设置切割后文件的前置文件名, split会自动在前置文件名后再加上编号
示例1:
使用指令split将文件a.txt每3行切割成一个文件,输入如下命令:
注意:是按照a.txt文件中的行数进行分割的,每3行切分到一个文件中,切割成多个以"x"开头的小文件。直至所有行数被分完。
[root@kevin ~]# cat a.txt
sdfsdf
123123123
sdfasdf2r345345
kljljkl
sjkdfjsdofopf
sadfsd2343
123123
asdf4555
66666
888888
[root@kevin ~]# split -3 a.txt
[root@kevin ~]# ls
anaconda-ks.cfg a.txt xaa xab xac xad
[root@kevin ~]# cat xaa
sdfsdf
123123123
sdfasdf2r345345
[root@kevin ~]# cat xab
kljljkl
sjkdfjsdofopf
sadfsd2343
[root@kevin ~]# cat xac
123123
asdf4555
66666
[root@kevin ~]# cat xad
888888
示例2:
有个文件要处理,因为很大,所以想把它切成若干份,每份N行,以便并行处理。
参数说明:
-b, --bytes=SIZE:对file进行切分,每个小文件大小为SIZE。可以指定单位b,k,m。
-l, --lines=NUMBER:对file进行切分,每个文件有NUMBER行。
prefix:分割后产生的文件名前缀。
示例:
假设要切分的文件为test.2012-08-16_17,大小1.2M,12081行。
1)
[root@kevin ~]# split -l 5000 test.2012-08-16_17
生成xaa,xab,xac三个文件。
[root@kevin ~]# wc -l #看到三个文件行数如下:
5000 xaa
5000 xab
2081 xac
12081 总计
2)
[root@kevin ~]# split -b 600k test.2012-08-16_17
生成xaa,xab两个文件
[root@kevin ~]# ls -lh #看到两个文件大小如下:
600K xaa
554K xab
3)
[root@kevin ~]# split -b 500k test.2012-08-16_17 example
得到三个文件,文件名的前缀都是example
[root@kevin ~]# ls -lh #看到文件信息如下:
500K exampleaa
500K exampleab
154K exampleac
示例3:
将一个大文件分成若干个小文件方法
例如将一个BLM.txt文件分成前缀为 BLM_ 的1000个小文件,后缀为系数形式,且后缀为4位数字形式
[root@kevin ~]# wc -l BLM.txt #读出 BLM.txt 文件一共有多少行
[root@kevin ~]# split -l 2482 ../BLM/BLM.txt -d -a 4 BLM_
将文件 BLM.txt 分成若干个小文件,每个文件2482行(-l 2482),文件前缀为BLM_ ,系数不是字母而是数字(-d),后缀系数为四位数(-a 4)
=====================================================
Linux下文件分割可以通过split命令来实现,可以指定按行数分割和安大小分割两种模式。Linux下文件合并可以通过cat命令来实现,非常简单。
在Linux下用split进行文件分割:
模式一:指定分割后文件行数
对与txt文本文件,可以通过指定分割后文件的行数来进行文件分割。
命令:split -l 300 large_file.txt new_file_prefix
模式二:指定分割后文件大小
split -b 10m server.log waynelog
对二进制文件我们同样也可以按文件大小来分隔。
在Linux下用cat进行文件合并:
命令:cat small_files* > large_file
将a.txt的内容输入到b.txt的末尾
cat a.txt >> b.txt
💕十二、comm命令:对于两个已排序文件,逐行比对
一、常用用法
comm FILE1 FILE2
二、含义与选项
2.1、含义
对于两个已排序的文件,逐行比对。
打印结果有3列:第1列,只属于“FILE1”的行;第2列,只属于“FILE2”的行;第3列,既属于“FILE1”,又属于“FILE2”的行。
2.2、选项表示的意思
“FILE1,FILE2”:指代已排序文件“FILE1”和“FILE2”
三、其他
3.1、“LC_COLLATE”等环境变量
由于涉及到两个字符串的比较等,故而程序实现中使用“LC_COLLATE”等环境变量,最终结果受到“LC_COLLATE”等环境变量的控制。
3.2、排序策略
comm命令实现设定的排序策略是“按照字典序排序”。两个已排序文件使用的排序策略组合共有3种情况。
3.2.1、情况1
一个排序文件按照字典序排序,另外一个排序文件按照非字典序(其他排序策略)排序。显而易见,在这种情况下,comm命令的执行结果会比较奇怪。
[root@localhost ~]# cat a.txt
001
02
3
10
[root@localhost ~]# cat b.txt
001
02
5
06
007
10
即已按照“数值大小”排序,执行“逐行比对”过程,我们的预期结果是:“3”只属于“c.txt”,“5,06,007”只属于“d.txt”,“001,02,10”共属于两个文件。
现在执行comm a.txt b.txt命令,得到如图1所示结果,不能达到预期。
[root@localhost ~]# comm a.txt b.txt
001
02
3
comm: file 1 is not in sorted order
10
5
comm: file 2 is not in sorted order
06
007
10
执行comm --nocheck-order a.txt b.txt命令,得到如图2所示结果,也不能达到预期。
[root@localhost ~]# comm --nocheck-order a.txt b.txt
001
02
3
10
5
06
007
10
两个文件都已按照字典序排序,这符合comm命令实现的设定,comm命令的执行结果能够达到预期。执行下述命令,得到如图3所示结果,结果符合预期。
[root@localhost ~]# sort a.txt > aa.txt
[root@localhost ~]# sort b.txt > bb.txt
[root@localhost ~]# comm aa.txt bb.txt
001
007
02
06
10
3
5
[root@localhost ~]# cat aa.txt
001
02
10
3
[root@localhost ~]# cat bb.txt
001
007
02
06
10
5
comm -1 file1 file2 比较两个文件的内容只删除 'file1' 所包含的内容
comm -2 file1 file2 比较两个文件的内容只删除 'file2' 所包含的内容
comm -3 file1 file2 比较两个文件的内容只删除两个文件共有的部分
💕join命令:根据两行中具有相同值的两个字段,将该两行内容拼接成一行打印输出
一、常用用法
join [-t CHAR] [-i] [--header] [-1 FIELD] [-2 FIELD] [-e STR] FILE1 FILE2
二、含义与选项
2.1、含义
存在两个已排序文件,假如文件1中的某条记录的某个字段值(默认是第一个字段,从1开始计数)与文件2中的某条记录的某个字段值
(默认是第一个字段,从1开始计数)一致,那么在最终打印结果中,将这两条记录拼接成一条记录。
2.2、选项表示的意思
“-t CHAR”:以“CHAR”字符作为记录内字段间的分隔符,默认的分隔符是“空格符”
“-i”:两个字段值比较时,忽略大小写
“–header”:两个文件的第一行作为说明行,不参与比较
“-1 FIELD”:FILE1中以第“FIELD”个字段作为比较字段
“-2 FIELD”:FILE2中以第“FIELD”个字段作为比较字段
“-e STR”:在最终的拼接记录中,如果某个字段的值为空,那么以“STR”替换
“FILE1”:文件1
“FILE2”:文件2
示例一
有文件“a.txt”和“b.txt”,内容分别如下:
[root@localhost ~]# cat a.txt
a 1
b 2
[root@localhost ~]# cat b.txt
a 3
b 4
执行以下命令,得到如下结果:
[root@localhost ~]# join a.txt b.txt
a 1 3
b 2 4
示例二
有文件“a.txt”和“b.txt”,内容分别如下:
[root@localhost ~]# cat a.txt
a;1
b;2
[root@localhost ~]# cat b.txt
a;3
b;4
执行以下命令,得到如下结果:
[root@localhost ~]# join -t ';' a.txt b.txt
a;1;3
b;2;4
示例三
有文件“a.txt”和“b.txt”,内容分别如下:
[root@localhost ~]# cat a.txt
A 1
b 2
[root@localhost ~]# cat b.txt
a 3
b 4
执行以下命令,得到如下结果:
[root@localhost ~]# join -i a.txt b.txt
A 1 3
b 2 4
示例四
有文件“a.txt”和“b.txt”,内容分别如下:
[root@localhost ~]# cat a.txt
Col1 Col2
a 1
b 2
[root@localhost ~]# cat b.txt
Col3 Col4
a 3
b 4
执行以下命令,得到如下结果:
[root@localhost ~]# join --header a.txt b.txt
Col1 Col2 Col4
a 1 3
b 2 4
示例五
有文件“a.txt”和“b.txt”,内容分别如下:
[root@localhost ~]# cat a.txt
a 1 f
b 2 g
[root@localhost ~]# cat b.txt
f 3 5
g 4 6
执行以下命令,得到如下结果:
[root@localhost ~]# join -1 3 -2 1 a.txt b.txt
f a 1 3 5
g b 2 4 6
示例六
有文件“a.txt”和“b.txt”,内容分别如下:
[root@localhost ~]# cat a.txt
a
b 2
[root@localhost ~]# cat b.txt
a 3
b 4
执行以下命令,得到如下结果:
[root@localhost ~]# join -e "hello world" a.txt b.txt
a hello world 3
b 2 4
四、其他
4.1、“LC_COLLATE”等环境变量
由于涉及到两个字符串的比较等,故而程序实现中使用“LC_COLLATE”等环境变量,最终结果受到“LC_COLLATE”等环境变量的控制。
4.2、排序策略
跟“comm”命令一样,join命令实现设定的排序策略是“按照字典序排序”。因而,两个文件“已排序”应该是按照字典序已排序,否则执行join命令得到的结果很有可能不能符合预期。