Linu进阶-Shell编程下-常用的shell工具(cut, sed, awk)(待复习完善)

九, 常用的Shell工具(cut, sed, awk, sort, grep)

9.1 cut : 剪切文件中的数据

cut的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出

[基本语法]

    cut [选项参数] 文件名
# 注意: 默认的分隔符是制表符
选项参数功能
-f列号, 提取第几列
-d分隔符, 按照指定分隔符分隔列
-b设定要提取每一行的多少个字节

[cut 的定位依据]

所谓"定位依据", 通俗来说就是, 我该告诉 cut 我想定位到那一段内容进行剪切呢?

cut命令共接受三类定位方法:

  1. 按字节(bytes)定位, 用-b选项;
  2. 按字符(characters)定位, 用-c选项;
  3. 按域(fields)定位, 用 -f选项;

对选项举栗子:

  1. -b (分割给定的字节, 一个英语字母就是一个字节哈)

    • -b 后面的数字表示的是分割显示出第几个字节,注意如果是个区间, 一定是闭区间噢

    • 需要注意一点,cut 命令如果使用了-b选项,那么在执行此命令时,cut 会先把 -b 后面所有的定位数字按照从小到大的顺序排序,然后再依次提取。所以你可以随意颠倒定位数字的顺序。比如下面这个例子就可以证明这个结论:

  2. -c (分割字符数, 如果使用 -b分割中文字符, 会发现无法正常显示, 这个时候就需要用到 -c选项)

用 -c 则会以字符为单位来提取内容;而 -b 只会傻傻地以字节(8 位二进制位)来计算,输出的就是乱码了。
当遇到多字节字符时,可以使用-n选项,-n选项用于告诉 cut 命令不要将多字节字符拆开,而是合并在一起显示。所以就有了上图中 -nb的使用方法;

  1. -f 因为刚才提到的 -b 和 -c 只能在固定格式的文档中提取信息,而对于非固定格式的文档则束手无策。这时候“域”就派上用场啦。

比如我们在/etc/passwd中以指定的分隔符来切割字符串, /etc/password文件的格式主要是用户名:口令:用户序号:组序号:注释性描述: 用户主目录: 登录shell, 我们可以搭配使用-d -f选项实现分割显示出 用户名:用户主目录:登录shell

[案例实操]

  1. 演示的cut.txt文本数据
    在这里插入图片描述

  2. 切割cut.txt 第一列

  3. 在cut.txt文件中切割出单独的一个字符 guan

  4. 选取系统 PATH变量值, 第二个":"开始后的所有路径


[拓展1]: 如何识别文件中的空格和制表符

  • 求助sed命令

通过使用sed -n l 文件名, 如果是制表符, 那么会显示为\t符号, 如果是空格, 就会原样显示.

注意: 上面的 sed -n 后面的字符是L的小写字母l.

[拓展2]: 设置cut 的间隔符为空格或制表符

cut 的 -d 选项的默认间隔符就是制表符(Tab),所以当你就是要使用制表符的时候,完全可以省略 -d 选项,而直接用 -f 选项来指定域就可以了。是不是幸福来得太突然了呢。

而如果你想将间隔符设置为空格,那么就按下面的例子来做就好了,其实就是用两个单引号将一个空格括起来:

[rocrocket@roclinux ~]$ cat tab_space.txt |cut -d ' ' -f 1
this
this

注意,两个单引号之间真的要有一个空格哦,不能偷懒。

而且,你只能在 -d 后面设置一个空格,不能设置多个空格,因为 cut 只允许间隔符是一个字符
#看看写两个空格的后果

[rocrocket@roclinux ~]$ cat tab_space.txt |cut -d '  ' -f 1
cut: the delimiter must be a single character
Try 'cut --help' for more information.

正好借着这个例子,让你说出 cut 命令的一个不足之处,你会如何回答呢?对,其中一个不足就是不善于处理“多空格”情况。

如果文件里面的某些域是由若干个空格来间隔的,那么用 cut 就有点麻烦了,因为 cut 只擅长处理“以一个字符间隔”的文本内容。

[拓展3] 为什么 ps和cut命令一起使用,总是会出现重复的行?
奇怪的重复现象

9.2 sed : 替换, 删除, 更新文件中的行内容

  • sed(stream edit), 即流编辑器;
  • sed工具是一个面向行的处理工具,以行为处理单位;
  • sed是一种流编辑器, 它一次处理一行内容. 处理时, 把当前处理的行存储在临时缓冲区中, 称为 “模式空间”, 接着用sed命令处理缓冲区中的内容, 处理完成后, 把缓冲区的内容送往屏幕(也就是标准输出(STOUT)). 接着处理下一行, 这样不断重复, 直到文件末尾.
  • sed命令不会对读取的文件做贸然的修改, 除非你使用重定向输出;

[基本语法]

sed [选项参数] '命令' 文件名
  • 选项参数
    选项参数功能
    -e直接在指令列模式上进行sed 的动作编辑
    -n警告sed, 除非是明确要输出的行,否则不要胡乱输出,搭配p使用
  • 命令(切记命令用''包围起来)
    命令功能
    a新增, a的后面可以接子串, 在下一行出现
    d删除
    s查找并替换
    p打印该行
    r读取指定文件的内容
    w写入指定文件

[案例实操]

  1. 添加(在指定行数后添加元素)

sed ‘5a sb’ x.txt (在 第5行的下一行添加 sb)

  1. 删除特定行,

sed ‘/target/d’ 文件名
主要文件含有target,就进行删除


  1. 替换,
    sed ‘s/xy/abc/g’ 文件名

把文件中的ss替换为abc
g为全局替换的意思(global),你可以发现下图栗子 有两个 wo wo都被替换为了 ni ni;

  1. -n 和 p的搭配使用, 输出想要输出的行

eg: sed -n ‘/4/p’ 文件名 输出含有4的行

输出passwd里面含有root的行

  1. 使用sed命令实现cut命令的效果

再来四个复杂点的栗子, 好好跟着做哈


sed -e 的使用

多个 command 之间,是按照在命令中的先后顺序来执行的。

深入学习sed命令的使用

9.3 awk命令

一个强大的文本分析工具, 把文件逐行的读入, 以空格为默认分隔符将每行切片, 切开的部分再进行分析处理;

[基本用法]

awk [选项参数] 'patter1{action1} pattern2{action2}...' filename
  • pattern: 表示 awl在数据中要查找的内容,就是匹配模式
  • action: 在找到匹配内容时所执行的一系列命令

选项参数:
|选项参数|功能|
|----|----|
|-F|指定输入文件拆分分隔符|
|-v|赋值一个用户定义变量|

[案例实操]
0. 数据准备(把/etc/passwd 移动到当前目录作为样本来使用)

  1. 搜索passwd文件以root关键字开头的所有行, 并输出该行的第7列;

  1. 搜索passwd文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。

注意:只有匹配了pattern的行才会执行action

  1. 只显示/etc/passwd的第一列和第七列,以逗号分割,且在添加列名user,shell作为输出的第一行, 添加"dahaige,/bin/zuishuai"作为输出的最后一行。

对begin和end 的解释
在Unix awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。

任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。

  1. 将passwd文件中的用户id增加数值1并输出

[awk的内置变量]

变量说明
FILENAME文件名
NR已读的记录数
NF浏览记录的域的个数(切割后, 列的个数)

对内置变量的案例实操:

  1. 统计passwd文件名,每行的行号,每行的列数

  2. 切割 IP

  3. 查询sed.txt中空行所在的行号

十, 几道面试题

  • 京东

问题1:使用Linux命令查询file1中空行所在的行号

问题2:有文件chengji.txt内容如下:
张三 40
李四 50
王五 60
使用Linux命令计算第二列的和并输出

  • 搜狐&和讯网
    问题1:Shell脚本里如何检查一个文件是否存在?如果不存在该如何处理?
    #!/bin/bash

if [ -f file.txt ]; then
echo “文件存在!”
else
echo “文件不存在!”
fi
11.3 新浪
问题1:用shell写一个脚本,对文本中无序的一列数字排序
[root@CentOS6-2 ~]# cat test.txt
9
8
7
6
5
4
3
2
10
1
[root@CentOS6-2 ~]# sort -n test.txt|awk '{a+=$0;print KaTeX parse error: Expected 'EOF', got '}' at position 2: 0}̲END{print "SUM=… grep -r “shen” /home | cut -d “:” -f 1
/home/atguigu/datas/sed.txt
/home/atguigu/datas/cut.txt
61715473)]

posted @ 2022-05-26 20:31  青松城  阅读(254)  评论(0编辑  收藏  举报