走进Linux_深入bash数据操作

引:在这里有一切你想要的bash数据操作知识,比如数据流重定向,管道命令,正则表达式的使用,大家可以快快进来!

数据流的重定向

什么是数据流重定向

一般来说,如果你要执行一个命令,通常它会是这样的:

  1. 文件 -> 标准输入 ->命令
  2. 如果执行正确,命令 -> 标准输出 -> 文件/设备;如果执行错误,命令 -> 标准错误输出 -> 文件或设备

标准输出,标准错误输出,标准输入

  1. 标准输出:指的是命令执行所回传的正确信息,代码为1,使用> 或 >>;
  2. 标准错误输出:指的是命令执行错误失败后,所回传的错误信息,代码为12,使用2> 或 2>>;
  3. 标准输入:将原本需要键盘输入的数据改由文件内容来替代,代码为0,使用< 或 <<;

如下面的命令:

1
ll / > ~/rootfile // 显示文件名信息到rootfile文件中

关于重定向输出文件的创建方式如下:

  1. 该文件如果不存在,系统会自动将它创建起来
  2. 当这个文件存在,那么系统就会将这个文件内容清空,然后再将数据写入
  3. 若以>输入到一个以存在的文件中,那个文件就会被覆盖,如果不想被覆盖,可以使用 >>

/dev/null 垃圾桶黑洞设备与特殊写法

  1. /dev/null 垃圾桶黑洞设备,如果我们知道错误信息会发生,所以要讲错误信息忽略掉而不显示或存储,我们就需要使用/dev/null这个黑洞设备了。写法如下:

    1
    ll /  2> /dev/null
  2. 如果我们要将正确地与错误数据都写入同一个文件中去,这个时候就需要使用特殊写法了,如下:

    1
    2
    ll / > ~/rootfile 2>&1  
    ll / &> ~/rootfile

为什么要使用命令输出重定向

  1. 屏幕输出的信息很重要,而且我们需要将它存下来的时候
  2. 后台执行中的程序,不希望它干扰屏幕正常的输出结果时
  3. 一些系统的例行命令的执行结果,希望它可以存下来时
  4. 一些执行命令的可能已知信息时,想以“2>/dev/null”将它丢掉时
  5. 错误信息与正确信息需要分别输出时

命令执行的判断依据:;, &&,||

在某些情况下,很多命令我们需要一次输入去执行,而不像分开执行,基本有两个选择,一个是通过shell script编写脚本去执行,一种是听过下面的介绍来一直输入多重命令。

  1. cmd ; cmd (不考虑命令相关性的连续命令执行,第一个命令执行结束后便会执行第二个命令)
  2. cmd && cmd (若第一个命令执行成功才会执行第二个命令;若第一个命令执行失败,则不会执行第二个命令。)
  3. cmd || cmd (若第一个命令执行成功,则不执行第二个命令;若第一个命令执行失败,才会执行第二个命令。)

管道命令(pipe)

什么是管道命令

管道命令 能够将一个命令的执行结果经过筛选,只保留我们需要的信息。 它的符号是 “ | ”

管道命令有下面两个比较需要注意的地方:

  1. 管道命令仅会处理标准输出,对于标准错误输出会予以忽略
  2. 管道命令必须要能够接收来自前一个命令的数据成为标准输人继续处理才行。

管道命令

选取指定列:cut

cut为剪切的意思,它能将一行行的数据按照指定的分隔符切成一列列,然后只显示特定列的数据。 cut有两种使用方式:

  • 按照指定字符分隔,这个命令会按照特定的分隔符将数据切分,并只显示第n列的数据。如下:

    1
    cut -d '分隔符' -f n(第几列)
  • 选择特定范围内的数据,如下:

    1
    cut -c 起始字符的下标-结束字符的下标

关键词搜索指定行:grep

grep用于进行关键词查找,它会将文件中含有关键词的那一整行输出来。grep的两种使用方式如下:

  • 从指定文件中将符合关键词的行搜索出来,如下:

    1
    grep [-参数] ‘关键词’ 文件
  • 采用管道,将前一个命令的执行结果输出给grep,并通过grep的关键词搜索将符合条件的行搜索出来,如下:

    1
    命令 | grep [-参数] ‘关键词’

排序:sort

sort命令能够将指定文件 或 前一个命令的结果数据 按照指定字段进行排序。sort两种使用方式与grep基本一样,一种是将文件中的数据按照指定字段排序。另一种是使用管道,将前一个命令执行的结果按照指定字段进行排序。。

去除重复行:uniq

该命令只能用于管道,如统计当前系统所有用户的登录次数:如下:

1
last | cut -d ' ' -f 1 | uniq -c

统计字数、行数、字符数:wc

wc只能通过管道使用,如下:

1
命令 | wc [-参数]

双向重定向:tee

tee只能和管道结合使用,如将last中的信息输出指文件并显示在屏幕上,指令如下:

1
last | tee -a lastfile | cut -d ' ' f 1

切割文件:split

该命令能将一个大文件切分成若干个小文件。用法如下:

1
split [-bl] 大文件 小文件名字前缀

正则表达式

什么是正则表达式

正则表达式 就是处理字符串的方法,它是行为单位来进行字符串的处理行为
正则表达式通过一些特殊符号的辅助,可以让用户轻易达到查找、删除、替换某特定字符串的处理程序。

正则表达式基本上就是一种“表示法”,只要工具支持这种表示法,那么工具程序就可以用来作为正则表达式的字符串处理之用。比如vi、grep、awk、sed等工具。

正则表达式的字符串表达方式依照不同的严谨度可以分为基本正则表达式扩展正则表达式

基础正则表达式

基础正则表达式字符

RE字符 意义
^word 待查找的字符串(word)在行首
word$ 待查找的字符串(word)在行尾
. 代表一定有一个任意字符的字符
\/ 转义字符,将特殊符号的特殊意义去除
* 重复0个或多个的前一个字符
[list] 从字符集合的RE字符里面找出想要选取的字符
[n1-n2] 从字符集合的RE字符里面找出想要选取的字符范围
[^list] 从字符集合的RE字符里面找出不要的字符串或范围
/{n,m/} 连续n到m个的前一个RE字符,/{n/}表示连续n个,/{n,/}表示连续n个及以上

PS:正则表达式的特殊字符与一般在命令行输入的“通配符”并不相同,通配符的*代表的是零到无限多个字符的意思,但是在正则表达式中*是表示重复0到无穷多个前一个RE字符的意思。

基础正则表达式练习(以grep工具为例)

  1. 查找特定字符串

    1
    2
    3
    grep -n ‘the’ regular_express.txt

    grep -vn 'the' regular_express.txt (-v反向选择)
  2. 利用中括号[]来查找集合字符

    1
    2
    3
    4
    5
    grep -n 't[ae]st' regular_express.txt (可匹配test或tast)

    grep -n '[^g]oo' regular_express.txt (oo前不能有g的字符)

    grep -n '[^[:lower:]]oo' regular_express.txt ([:lower:]代表a-z的意思)
  3. 行首和行尾字符

    1
    2
    3
    grep -n '^test' regular_express.txt (注:^在[]内表示“反向选择”,在[]外表示定位在行首)

    grep -n '/.$' regular_express.txt (找出行尾结束为小数点的那一行)
  4. 任意一个字符.与重复字符*

    1
    2
    3
    4
    5
    grep -n ‘g..d’ regular_express.txt (可匹配good,glad等字符)

    grep -n 'ooo*' regular_express.txt (匹配至少两个o以上的字符)

    grep -n 'g.*g' regular_express.txt (找出g开头与g结尾的字符串,.*表示o个或多个任意字符的意思)
  5. 限定连续RE(Regular Expression)字符范围{}

    1
    2
    3
    4
    5
    grep -n 'o/{2/}' regular_express.txt (找出两个o的字符串)

    grep -n ‘go/{2,5/}g’ regular_express.txt (g后有两个到5个o,然后接一个g的字符串)

    grep -n ‘go/{2,/}g’ regular_express.txt (g后有两个及以上的o,然后接一个g的字符串)

sed工具

sed本身是一个管道命令,它可以将数据进行替换、删除、新增、选取特定行等功能。使用方式如下:

1
sed [-nefr] [动作]

扩展正则表达式

一般情况下只需要基础正则表达式即可,但是有时候还需要一些扩展功能,比如整合两条管道命令,这就需要用到扩展正则表达式,如果是grep,它基本使用命令是egrep,基本的符号如下:

字符 意义与范例
+ 重复一个或多个的前一个RE字符,如:egrep -n ‘go+d’ regular_express.txt
? 0个或一个的前一个RE字符,如:egrep -n ‘go?d’ regular_express.txt
\ 用或的方式找出字符串,如:egrep -n ‘gd\ good’ regular_express.txt
() 找出“组”的字符串 (如:egrep -n ‘g(la \ oo)d’ regular_express.txt 表示找出glad或good字符串)
()+ 多个重复组的判别 (如echo ‘AxyzxyzxyzxyzC’ \ egrep ‘A(xyz)+C’ 找出开头是A结尾是C,中间有一个以上的“xyz”字符串)

文件的格式化处理

文件格式化:printf

如果我们需要将自己的数据给它格式化输出,我们就需要一个好的样式,输出的方式其实和C语言的格式化输出差不多,如下:

1
printf '打印格式' 实际内容

好用的数据处理工具:awk

awk相当适合处理小型的数据,它的基本用法如下:

1
2
3
4
awk ‘条件类型1{动作1} 条件类型2{动作2} ...’ filename

// 例子
last -n 5 | awk '{print $1 "\t" $3}' // 取出登录者账号和ip

这个awk的处理流程如下:

  1. 读入第一行,并将第一行的填入$0,$1等变量中
  2. 依据条件类型的限制,判断是否需要进行后面的动作
  3. 做完所有的动作与条件类型
  4. 若还有后续行,就重复上面1~3的步骤,直到所有数据都读完为止。

文件比较工具:diff

diff用于比较两个文件之间的区别,并且是以行为单位的,diff也可以比较两个目录。用法如下:

1
diff [-bBi] from-file to-file

patch这个命令与diff有密不可分的联系,将旧的文件升级成为新的文件的方法是先比较新旧版本的区别,将将区别文件制作成为补丁文件,再有补丁问价更新旧文件即可。例子如下:

1
2
3
4
5
6
7
8
9
10
11
// 范例:以/tmp/test内的passwd.old 与passwd.new 制作补丁文件,并更新旧版数据

diff -Naur passwd.old passwd.new >passwd.patch

// 更新旧文件,变成和新文件一样

patch -p0 < passwd.patch

// 恢复旧文件的内容

patch -R -p0 < passwd.patch

参考

  1. 《鸟哥的Linux私房菜》