五 Linux Shell常用命令[sort,uniq,mktemp,split,csplit]

一 排序

   sort命令能够对文本文件和stdin进行排序.它可以配合其他命令来生成所需要的输出.uniq经常和sort一同使用,提取不重复(或重复)的行.

  sort的用法

#可以按照下面的方式排序一组文件
$ sort file1.txt file2.txt > sorted.txt
或是
$ sort file1.txt file2.txt -o sorted.txt

#按照数字排序
sort -n file.txt
#按照逆序排序
sort -r file.txt
#按照月份排序((依照一月、二月、三月……),英文的月数也可以)
sort -M file.txt
#合并两个已排序过的文件
sort -m sorted1 sorted2
#找出已排序文件中不重复的行
sort file1.txt file2.txt | uniq

#检查文件是否已经排序过

#!/bin/bash
#功能描述:排序
sort -C filename ;
if [ $? -eq 0 ]; then
echo Sorted;
else
echo Unsorted;
fi

#####测试数据#####

[root@rwwh rh]# cat data.txt
1 mac 2000
2 winxp 4000
3 bsd 1000
4 linux 1000

#依照第一列,逆序形式排序

[root@rwwh rh]# sort -nrk 1 data.txt
4 linux 1000
3 bsd 1000
2 winxp 4000
1 mac 2000

#依照第二列进行排序

[root@rwwh rh]# sort -k 2 data.txt
3 bsd 1000
4 linux 1000
1 mac 2000
2 winxp 4000

#注意:sort命令对于字母表排序和数字排序有不同的处理方式,因此,如果采用数字顺序排序,就应该明确地给出-n选项
#说明:-k后的整数指定了文本文件中的某一列.列与列直接由空格分隔.若需要将特定范围内的一组字符(例如.第二列中的第4-5个字符)
#作为键,应该使用点号分隔的两个整数来定义一个字符位置,然后将范围内的第一个字符和最后一个字符用逗号连接起来.

 #若需要忽略空格之类的多余字符并以字典排序
sort -bd unsorted.txt

 ###这里想不通,回头再想想

 

 uniq的用法

     uniq 命令可以从给定输入中( stdin 或命令行参数指定的文件)找出唯一的行,报告或删除那些重复的行.uniq只能作用于排过序的数据,因此uniq通常都与sort命令结合使用

##测试数据
[root@rwwh rh]# cat sort11.txt 
hack
bash
foss
hack
hack
#删除重复的行
[root@rwwh rh]# sort sort11.txt |uniq 
bash
foss
hack
#只显示不重复的行
[root@rwwh rh]# sort sort11.txt |uniq -u
bash
fos
#只显示重复的行
[root@rwwh rh]# sort sort11.txt |uniq -d
hack
#统计各行在文件中出现的次数
[root@rwwh rh]# sort sort11.txt |uniq -c
      1 bash
      1 foss
      3 hack

将命令输出作为 xargs 命令的输入时,最好为输出的各行添加一个0值字节(zero-byte)
终止符。使用 uniq 命令的输入作为 xargs 的数据源时,同样应当如此。如果没有使用0值字节终
止符,那么在默认情况下, xargs 命令会用空格来分割参数。例如,来自 stdin 的文本行“this is
a line”会被 xargs 视为4个不同的参数。如果使用0值字节终止符,那么 \0 就被作为定界符,此时,
包含空格的行就能够被正确地解析为单个参数

-z 选项可以生成由0值字节终止的输出:
$ uniq -z file.txt
下面的命令将删除所有指定的文件,这些文件的名字是从files.txt中读取的:
$ uniq -z file.txt | xargs -0 rm
如果某个文件名出现多次, uniq 命令只会将这个文件名写入 stdout 一次,这样就可以避免
出现 rm: cannot remove FILENAME: No such file or directory

 #看不懂,回头再想想

 二 临时文件命名与随机数

  shell脚本经常需要存储临时数据。最适合存储临时数据的位置是 /tmp(该目录中的内容在系统重启后会被清空)。有两种方法可以为临时数据生成标准的文件名

   mktemp 命令的用法非常简单。它生成一个具有唯一名称的文件并返回该文件名(如果创建
     的是目录,则返回目录名)。
   如果提供了定制模板, X 会被随机的字符(字母或数字)替换。注意, mktemp 正常工作的前
提是保证模板中至少要有3个 X 。

#创建临时文件
[root@rwwh rh]# filename=`mktemp`
[root@rwwh rh]# echo $filename
/tmp/tmp.hCUnPHK3KA
#创建临时目录
[root@rwwh rh]# dirname=`mktemp -d`
[root@rwwh rh]# echo $dirname
/tmp/tmp.fp04cPS9yl

#若仅仅想生成文件名,不希望创建实际的文件或目录

[root@rwwh tmp.fp04cPS9yl]# tmpfile=`mktemp -u`
[root@rwwh tmp.fp04cPS9yl]# echo $tmpfile
/tmp/tmp.UGZdP6NcBt
#基于模板创建临时文件名

[root@rwwh tmp.fp04cPS9yl]# mktemp test.XXX
test.8EL
[root@rwwh tmp.fp04cPS9yl]# mktemp XXX.txt
91t.txt

 三 分割文件与数据

 split

  split命令可以用来分割文件.该命令接受文件名作为参数,然后创建出一系列体积更小的文件,其中依据字母序排在首位的那个文件对应于原始文件的第一部分,排在次序的文件对应于原始文件的第二部分,以此类推.

  例如,通过指定分割大小,可以将100KB的文件分成一系列10KB的小文件。在 split 命令中,除了 k (KB),我们还可以使用 M (MB)、 G (GB)、 c (byte)和 w (word)

$ split -b 10k data.file
$ ls
data.file xaa xab xac xad xae xaf xag xah xai xaj
上面的命令将data.file分割成了10个大小为10KB的文件。这些新文件以 xab 、 xac 、 xad 的形
式命名。 split 默认使用字母后缀。如果想使用数字后缀,需要使用 -d 选项。此外,  -a length
可以指定后缀长度:
$ split -b 10k data.file -d -a 4
$ ls
data.file x0009 x0019 x0029 x0039 x0049 x0059 x0069 x0079
#为分割后的文件制定能够文件名前缀

$ split -b 10k data.file -d -a 4 split_file
$ ls
data.file split_file0002 split_file0005 split_file0008
strtok.c
split_file0000 split_file0003 split_file0006 split_file0009
split_file0001 split_file0004 split_file0007

  #若不想按照数据块大小,而是根据行数分割文件的话,可以使用-l num_of_lines:

   # 分割成多个文件,每个文件包含10 行
    $ split -l 10 data.fil

 csplit

csplit 实用工具能够基于上下文来分隔文件。它依据的是行计数或正则表达式。这个工具对于日志文件分割尤为有用.

#测试数据
$ cat server.log
SERVER-1
[connection] 192.168.0.1 success
[connection] 192.168.0.2 failed
[disconnect] 192.168.0.3 pending
[connection] 192.168.0.4 success
SERVER-2
[connection] 192.168.0.1 failed
[connection] 192.168.0.2 failed
[disconnect] 192.168.0.3 success
[connection] 192.168.0.4 failed
SERVER-3
[connection] 192.168.0.1 pending
[connection] 192.168.0.2 pending
[disconnect] 192.168.0.3 pending
[connection] 192.168.0.4 failed

#需求:将这个日志文件分割成server1.log、server2.log和server3.log,这些文件的内容分别取自原文件中不同的 SERVER 部分
#实现
$ csplit server.log /SERVER/ -n 2 -s {*} -f server -b "%02d.log"
$ rm server00.log
$ ls
server01.log server02.log server03.log server.log
下面是这个命令的详细说明。
  /SERVER/ 用来匹配特定行,分割过程即从此处开始。
  /[REGEX]/ 用于描述文本模式。它从当前行(第一行)一直复制到(但不包括)包含 SERVER
的匹配行。
  {*} 表示根据匹配重复执行分割操作,直到文件末尾为止。可以用{ 整数}的形式来指定分
割执行的次数。
  -s 使命令进入静默模式,不打印其他信息。
  -n 指定分割后的文件名后缀的数字个数,例如01、02、03等。
  -f 指定分割后的文件名前缀(在上面的例子中,server就是前缀)。
  -b  指定后缀格式。例如 %02d.log ,类似于C语言中 printf 的参数格式。在这里:文件
名 = 前缀 + 后缀,也就是 server + %02d.log 。
因为分割后得到的第一个文件没有任何内容(匹配的单词就位于文件的第一行中),所以我
们删除了server00.log

 四 根据扩展名切分文件名

  借助%操作符可以从name.extension这种格式中提取name部分(文件名)


[root@rwwh ~]# file_jpg="sample.jpg"
${VAR.*}含义如下:
①从$VAR中删除位于%右侧的通配符(在上例中是.*)所匹配的字符串,通配符从右往左进行匹配.
②给VAR赋值,即VAR=sample.jpg.通配符从右往左匹配到的内容是.jpg,因此从$VAR中删除匹配结果,得到输出sample [root@rwwh ~]# name=${file_jpg%.*} [root@rwwh ~]# echo File name is: $name File name is: sample

 %属于非贪婪(non-greedy)操作.它从右向左找出匹配通配符的最短结果.还有另一个操作符%%,它与%相似,但行为模式确实贪婪的,这意味着它会匹配符合通配符的最长结果

 

[root@rwwh ~]# VAR=hack.fun.book.txt
[root@rwwh ~]# echo ${VAR%.*}
hack.fun.book
[root@rwwh ~]# echo ${VAR%%.*}
hack

  借助#操作符可以提取出扩展名,这个操作符与%相似,不过求值方向是从左向右

${VAR#*.}的含义如下:
从$VAR中删除位于#右侧的通配符(即*.)从左向右所匹配的字符串
[root@rwwh ~]# extension=${file_jpg#*.} [root@rwwh ~]# echo Extension is:$extension Extension is:jpg
和 %% 类似, # 也有一个对应的贪婪操作符 ##,## 从左向右进行贪婪匹配,并从指定变量中删除匹配结果
[root@rwwh ~]# VAR=hack.fun.book.txt

[root@rwwh ~]# echo ${VAR#*.}
fun.book.txt
[root@rwwh ~]# echo ${VAR##*.}
txt

#假定URL为www.google.com

$ echo ${URL%.*} # 移除.* 所匹配的最右边的内容
www.google
$ echo ${URL%%.*} # 将从右边开始一直匹配到最左边的.* (贪婪操作符)移除
www

$ echo ${URL#*.} # 移除 *. 所匹配的最左边的内容
google.com
$ echo ${URL##*.} # 将从左边开始一直匹配到最右边的*. (贪婪操作符)移除
com

 

posted on 2020-06-20 14:45  rwwh  阅读(229)  评论(0)    收藏  举报

导航