美文网首页
shell编程-2021-07-21

shell编程-2021-07-21

作者: 喜忧参半 | 来源:发表于2021-07-20 21:31 被阅读0次

一、 正则表达式

1.概述

因为用来在文件当中搜索字符串的命令,如 grep、awk、sed等命令可以支持正则表达式,而在系统当中搜索文件的命令,如 ls、find、cp这些命令不支持正则表达式,所以只能使用 shell自己的通配符来进行匹配了。

2.基础正则表达式

元字符 作 用
* 前一个字符匹配 0 次或任意多次。
. 匹配除了换行符外任意一个字符。
^ 匹配行首。例如:^hello 会匹配以 hello 开头的行。
$ 匹配行尾。例如:hello&会匹配以 hello 结尾的行。
[] 匹配中括号中指定的任意一个字符,只匹配一个字符。例如:[aoeiu] 匹配任意一个元音字母,[0-9] 匹配任意一位数字,[a-z][0-9]匹配小写字和一位数字构成的两位字符。
[^] 匹配除中括号的字符以外的任意一个字符。例如:[^0-9] 匹配任意一位非数字字符,[^a-z] 表示任意一位非小写字母。
\ 转义符。用于取消讲特殊符号的含义取消。
{n\} 表示其前面的字符恰好出现 n 次。例如:[0-9]\{4\} 匹配 4 位数字,[1][3-8][0-9]\{9\} 匹配手机号码。{n,} 表示其前面的字符出现不小于 n 次。例如: [0-9]{2,\} 表示两位及以上的数字。
{n,m} 表示其前面的字符至少出现 n 次,最多出现 m 次。例如:[a-z]{6,8}匹配 6 到 8 位的小写字母。

在~/.bashrc 文件中建立这个别名:

[root@localhost  ~]$  vi  /root/.bashrc
alias  grep='grep  --color=auto'

1. 练习文件建立

[root@localhost  ~]#  vi  test_rule.txt
Mr.  Li  Ming  said:
he  was  the  most  honest  man.
123despise  him
But  since  Mr.  shen  Chao  came,
he  never  saaaid  those  words.
5555nice!
because,actuaaaally,
Mr.  Shen  Chao  is  the  most  honest  man
Later,Mr.  Li  ming  soid  his  hot  bod

2. “.” 匹配除了换行符外任意一个字符

正则表达式“.”只能匹配一个字符,这个字符可以是任意字符,举个例子:
[root@localhost  ~]#  grep  "s..d"  test_rule.txt
Mr.  Li  Ming  said:
Later,Mr.  Li  ming  soid  his  hot  body.
#“s..d”会匹配在 s 和 d 这两个字母之间一定有两个字符的单词

[root@localhost  ~]#  grep  "s.*d"  test_rule.txt
Mr.  Li  Ming  said:
he  never  saaaid  those  words.
Later,Mr.  Li  ming  soid  his  hot  body.
#最后一句话比较有意思,匹配的是“soid  his  hot bod”
[root@localhost  ~]#  grep  ".*"  test_rule.txt

3. “^”匹配行首,“$”匹配行尾

“^”代表匹配行首,比如“^M”会匹配以大写“M”开头的行:
[root@localhost  ~]$  grep  "^M"  test_rule.txt
Mr.  Li  Ming  said:
Mr.  phato  is  the  most  honest  man
“$”代表匹配行尾,如果“n$”会匹配以小写“n”结尾的行:
[root@localhost  ~]$  grep  "n$"  test_rule.txt
Mr.  phato  is  the  most  honest  man
而“^$”则会匹配空白行:
[root@localhost  ~]$  grep  -n  "^$"  test_rule.txt\

4. “[ ]” 匹配中括号中指定的任意一个字符,只匹配一个字符

“[]”会匹配中括号中指定任意一个字符,注意只能匹配一个字符。
字符,要不会匹配一个 o 字符:
[root@localhost  ~]#  grep  "s[ao]id"  test_rule.txt
而“[0-9]”会匹配任意一个数字,如:
[root@localhost  ~]#  grep  "[0-9]"  test_rule.txt
而“[A-Z]”则会匹配一个大写字母,如:
[root@localhost  ~]#  grep  "[A-Z]"  test_rule.txt
如果正则是“^[a-z]”代表匹配用小写字母开头的行:
[root@localhost  ~]$  grep  "^[a-z]"  test_rule.txt

5. "\" 转义符

[root@localhost  ~]$  grep  "\.$"  test_rule.txt

6. “{n\}”表示其前面的字符恰好出现 n 次.

[root@localhost  ~]$  grep  "a\{3\}"  test_rule.txt
上面的两行都包含三个连续的  a,所以都会匹配。但是如果先要只显示三个连续的  a,可以这样
来写正则:
[root@localhost  ~]$  grep  "[su]a\{3\}[il]"  test_rule.txt
如果正则是“[0-9]\{3\}”则会匹配包含连续的三个数字的字符串:
[root@localhost  ~]$  grep  "[0-9]\{3\}"  test_rule.txt
虽然“5555”有四个连续的数字,但是包含三个连续的数字,所以也是可以列出的。可是这样不
能体现出来“[0-9]\{3\}”只能匹配三个连续的数字,而不能匹配四个连续的数字。那么正则就应该
这样来写“^[0-9]\{3\}[a-z]”:
[root@localhost  ~]$  grep  "^[0-9]\{3\}[a-z]"  test_rule.txt
123despise  him.
只匹配用连续三个数字开头的行

7. “{n,\}”表示其前面的字符出现不小于 n 次

[root@localhost  ~]$  grep  "^[0-9]\{3,\}[a-z]"  test_rule.txt
而“[su]a\{3,\}[il]”正则则会匹配在字母 s 或 u 和 i 或 l 之间,最少出现三个连续的 a 的字
符串:
[root@localhost  ~]$  grep  "[su]a\{3,\}[il]"  test_rule.txt
10)“\{n,m\}”匹配其前面的字符至少出现 n 次,最多出现 m 次
[root@localhost  ~]$  grep  "sa\{1,3\}i"  test_rule.txt
匹配在字母 s 和字母 i 之间有最少一个 a,最多三个a
[root@localhost  ~]$  grep  "sa\{2,3\}i"  test_rule.txt
匹配在字母 s 和字母 i 之间有最少两个 a,最多三个a

3. 扩展正则表达式

熟悉正则表达式的童鞋应该很疑惑,在正则表达式中应该还可以支持一些元字符,比如“+”,“?”,“|”,“()”。其实 Linux 是支持这些元字符的,只是 grep 命令默认不支持而已。如果要想支持这些元字符,必须使用 egrep 命令或 grep -E 选项,所以我们又把这些元字符称作扩展元字符。
如果查询 grep 的帮助,对 egrep 的说明就是和 grep -E 选项一样的命令,所以我们可以把两个命令当做别名来对待。通过表 12-2 来看看 Shell 中支持的扩展元字符:

扩展元字符 作 用
+ 前一个字符匹配 1 次或任意多次。
如“go+gle”会匹配“gogle”、“google”或“gooogle”,当然如果“o”有更多个,也能匹配。
前一个字符匹配 0 次或 1 次。
如“colou?r”可以匹配“colour”或“color”。
匹配两个或多个分支选择。
如“was|his”会匹配既包含“was”的行,也匹配包含“his”的行。
() 匹配其整体为一个字符,即模式单元。可以理解为由多个单个字符组成的大字符。
如“(dog)+”会匹配“dog”、“dogdog”、“dogdogdog”等,因为被()包含的字符会当成一个整体。
但“hello(world|earth)”会匹配“hello world”及“hello earth”。

二、字符截取和替换命令

1. cut列提取命令

[root@localhost ~]# cut [选项] 文件名
选项:
-f 列号: 提取第几列
-d 分隔符: 按照指定分隔符分割列
-c 字符范围: 不依赖分隔符来区分列,而是通过字符范围(行首为 0)来进行字段提取。
“n-”表示从第 n 个字符到行尾;“n-m”从第 n 个字符到第 m个字符;“-m”表示从第 1 个字符到第 m 个字符。
cut 命令的默认分隔符是制表符,也就是“tab”键,不过对空格符可是支持的不怎么好啊。我们
先建立一个测试文件,然后看看 cut 命令的作用吧:

[root@localhost  ~]#  vi  student.txt
ID  Name    gender  Mark
1   Liming  M   86
2   Sc  M   90
3   Tg  M   83

[root@localhost  ~]$  cut  -f  2  student.txt
#提取第二列内容

那如果想要提取多列呢?只要列号直接用“,”分开,命令如下:
[root@localhost  ~]$  cut  -f  2,3  student.txt
cut 可以按照字符提取,需要注意“8-”代表的是提取所有行的第十个字符开始到行尾
而“10-20”代表提取所有行的第十个字符到第二十个字符,
而“-8”代表提取所有行从行首到第八个字符:
[root@localhost  ~]$  cut  -c  8-  student.txt
#提取第八个字符开始到行尾,好像很乱啊,那是因为每行的字符个数不相等啊
[root@localhost  ~]$  cut  -d  ":"  -f  1,3  /etc/passwd
#以“:”作为分隔符,提取/etc/passwd 文件的第一列和第三列
如果想用 cut 命令截取 df 命令的第一列和第三列,就会出现这样的情况:
[root@localhost  ~]$  df  -h  |  cut  -d  "  "  -f  1,3

2. awk编程

1.printf格式化输出

[root@localhost ~]$ printf ‘输出类型输出格式’ 输出内容
输出类型:
%ns: 输出字符串。n 是数字指代输出几个字符
%ni: 输出整数。n 是数字指代输出几个数字
%m.nf: 输出浮点数。m 和 n 是数字,指代输出的整数位数和小数位数。如%8.2f
代表共输出 8 位数,其中 2 位是小数,6 位是整数。
输出格式:
\a: 输出警告声音
\b: 输出退格键,也就是 Backspace 键
\f: 清除屏幕
\n: 换行
\r: 回车,也就是 Enter 键
\t: 水平输出退格键,也就是 Tab 键
\v: 垂直输出退格键,也就是 Tab 键

为了演示 printf 命令,我们需要修改下刚刚 cut 命令使用的 student.txt 文件,文件内容如下:
[root@localhost  ~]$  vi  student.txt
ID  Name    PHP Linux   MySQL   Average
1   Liming  82  95  86  87.66
2   Sc  74  96  87  85.66
3   Tg  99  83  93  91.66
我们使用 printf 命令输出下这个文件的内容:
[root@localhost  ~]$  printf  '%s'  $(cat  student.txt)
IDNamegenderPHPLinuxMySQLAverage1LimingM82958687.662ScM74968785.663TgM99839391.66
就是  printf  命令,如果不指定输出格式,则会把所有输出内容连在
一起输出。其实文本的输出本身就是这样的,cat  等文本输出命令之所以可以按照格式漂亮的输出,
那是因为 cat 命令已经设定了输出格式。那么为了用 printf 输出合理的格式,应该这样做:
[root@localhost  ~]$  printf  '%s\t  %s\t  %s\t  %s\t  %s\t  %s\t  \n'  $(cat  student.txt)
#注意在 printf 命令的单引号中,只能识别格式输出符号,而手工输入的空格是无效的
ID  Name    PHP Linux   MySQL   Average
1   Liming  82  95  86  87.66
2   Sc  74  96  87  85.66
3   Tg  99  83  93  91.66

如果不想把成绩当成字符串输出,而是按照整型和浮点型输出,则要这样:
[root@localhost  ~]$  printf  '%i\t  %s\t  %i\t  %i\t  %i\t  %8.2f\t  \n'  \ 
$(cat  student.txt  |  grep  -v  Name)

2. awk 基本使用

[root@localhost ~]# awk ‘条件 1{动作 1} 条件 2{动作 2}…’ 文件名
条件(Pattern):
一般使用关系表达式作为条件。这些关系表达式非常多,具体参考表 12-3 所示,例如:
x > 10 判断变量 x 是否大于 10
x == y 判断变量 x 是否等于变量 y
A ~ B 判断字符串 A 中是否包含能匹配 B 表达式的子字符串
A !~ B 判断字符串 A 中是否不包含能匹配 B 表达式的子字符串
动作(Action):
格式化输出
流程控制语句

我们这里先来学习 awk 基本用法,也就是只看看格式化输出动作是干什么的。
至于条件类型和流程控制语句我们在后面再详细介绍。那看看这个例子吧:
[root@localhost  ~]#  awk  '{printf  $2  "\t"  $6  "\n"}'  student.txt
#输出第二列和第六列
比如刚刚截取 df 命令的结果时,cut 命令已经力不从心了,我们来看看 awk 命令:
[root@localhost  ~]#  df  -h  |  awk  '{print  $1  "\t"  $3}'

3. awk 的条件

条件的类型 条 件 说 明
awk 保留字 BEGIN

END
在 awk 程序一开始时,尚未读取任何数据之前执行。BEGIN 后的动作只在程序开始时执行一次
在 awk 程序处理完所有数据,即将结束时执行。END 后的动作只在程序结束时执行一次
关系运算符 > 大于
关系运算符 < 小于
关系运算符 >= 大于等于
关系运算符 <= 小于等于
关系运算符 == 等于。用于判断两个值是否相等,如果是给变量赋值,请使用“=”号
关系运算符 != 不等于
关系运算符 A~B 判断字符串 A 中是否包含能匹配 B 表达式的子字符串
关系运算符 A!~B 判断字符串 A 中是否不包含能匹配 B 表达式的子字符串
正则表达式 /正则/ 如果在“//”中可以写入字符,也可以支持正则表达式
  • BEGIN
    BEGIN 是 awk 的保留字,是一种特殊的条件类型。BEGIN 的执行时机是“在 awk 程序一开始时,尚未读取任何数据之前执行”。一旦 BEGIN 后的动作执行一次,当 awk 开始从文件中读入数据,BEGIN的条件就不再成立,所以 BEGIN 定义的动作只能被执行一次。例如:
[root@localhost  ~]$  awk  'BEGIN{printf  "This  is  a  transcript  \n"  }
{printf  $2  "\t"  $6  "\n"}'  student.txt
awk 命令只要检测不到完整的单引号不会执行,所以这个命令的换行不用加入“\”,就是一行命令
这里定义了两个动作
第一个动作使用 BEGIN 条件,所以会在读入文件数据前打印“这是一张成绩单”(只会执行一次)
第二个动作会打印文件的第二字段和第六字段
  • END
    END 也是 awk 保留字,不过刚好和 BEGIN 相反。END 是在 awk 程序处理完所有数据,即将结束时执行。END 后的动作只在程序结束时执行一次。例如:
[root@localhost  ~]$  awk  'END{printf  "The  End  \n"  }
{printf  $2  "\t"  $6  "\n"}'  student.txt
在输出结尾输入“The  End”,这并不是文档本身的内容,而且只会执行一次
  • 关系运算符
    举几个例子看看关系运算符。假设我想看看平均成绩大于等于 87 分的学员是谁,就可以这样输入命令:
[root@localhost  ~]$  cat  student.txt  |  grep  -v  Name  | \
awk  '$6  >=  87  {printf  $2  "\n"  }'
使用 cat 输出文件内容,用 grep 取反包含“Name”的行
判断第六字段(平均成绩)大于等于 87 分的行,
如果判断式成立,则打第六列(学员名)

加入了条件之后,只有条件成立动作才会执行,如果条件不满足,则动作则不运行。通过这个实
验,大家可以发现,虽然 awk 是列提取命令,但是也要按行来读入的。这个命令的执行过程是这样的:
1) 如果有 BEGIN 条件,则先执行 BEGIN 定义的动作
2.1) 如果没有 BEGIN 条件,则读入第一行,把第一行的数据依次赋予$0、$1、$2 等变量。其中$0代表此行的整体数据,$1 代表第一字段,$2 代表第二字段。
2.2) 依据条件类型判断动作是否执行。如果条件符合,则执行动作,否则读入下一行数据。如果没有条件,则每行都执行动作。
3) 读入下一行数据,重复执行以上步骤。

例如查看 Sc 用户的平均成绩:
[root@phato  ~]# awk  '$2 ~ /Sc/  {printf  $6  "\n"}'student.txt
#如果第二字段中输入包含有“Sc”字符,则打印第六字段数据
85.66
  • 正则表达式
    如果要想让 awk 识别字符串,必须使用“//”包含,例如:
    例子 1:
[root@localhost  ~]#  awk  '/Liming/  {print}'  student.txt
#打印 Liming 的成绩
当使用  df  命令查看分区使用情况是,如果我只想查看真正的系统分区的使用状况,而不想查看
光盘和临时分区的使用状况,则可以:
[root@localhost  ~]#  df  -h  |  awk  '/sda[0-9]/  {printf  $1  "\t"  $5  "\n"}  '
#查询包含有 sda 数字的行,并打印第一字段和第五字段

4. awk内置变量

awk 内置变量 作 用
$0 代表目前 awk 所读入的整行数据。我们已知 awk 是一行一行读入数据的,
$0 就代表当前读入行的整行数据。
$n 代表目前读入行的第 n 个字段。
NF 当前行拥有的字段(列)总数。
NR 当前 awk 所处理的行,是总数据的第几行。
FS 用户定义分隔符。awk 的默认分隔符是任何空格,如果想要使用其他分隔符(如“:”),就需要 FS 变量定义。
ARGC 命令行参数个数。
ARGV 命令行参数数组。
FNR 当前文件中的当前记录数(对输入文件起始为1)。
OFMT 数值的输出格式(默认为%.6g)。
OFS 输出字段的分隔符(默认为空格)。
ORS 输出记录分隔符(默认为换行符)。
RS 输入记录分隔符(默认为换行符)。
[root@localhost  ~]$  cat  /etc/passwd  |  grep  "/bin/bash"  |  \
awk  '{FS=":"}  {printf  $1  "\t"  $3  "\n"}'
#查询可以登录的用户的用户名和 UID
这里“:”分隔符生效了,可是第一行却没有起作用,原来我们忘记了“BEGIN”条件,那么再
来试试:
[root@localhost  ~]$  cat  /etc/passwd  |  grep  "/bin/bash"  |  \
awk  'BEGIN  {FS=":"}  {printf  $1  "\t"  $3  "\n"}'

[root@localhost  ~]$  cat  /etc/passwd  |  grep  "/bin/bash"  |  \
awk  'BEGIN  {FS=":"}  {printf  $1  "\t"  $3  "\t  行号:"  NR  "\t  字段数:"  NF  "\n"}'
#解释下 awk 命令
#开始执行{分隔符是“:”}  {输出第一字段和第三字段  输出行号(NR 值)  字段数(NF 值)}
root    0   行号:1    字段数:7
user1   501 行号:2    字段数:7
如果我只想看看 sshd 这个伪用户的相关信息,则可以这样使用:
[root@localhost  ~]$  cat  /etc/passwd  |  \
awk 'BEGIN {FS=":"} $1=="sshd" {printf $1 "\t" $3 "\t  行号:"NR "\t  字 段数:"F "\n"}'
#可以看到 sshd 伪用户的 UID 是 74,是/etc/passwd 文件的第 28 行,此行有 7 个字段

6. awk流程控制

我们再来利用下 student.txt 文件做个练习,后面的使用比较复杂,
我们再看看这个文件的内容:
[root@localhost  ~]#  cat  student.txt
ID  Name    PHP Linux   MySQL   Average
1   Liming  82  95  86  87.66
2     Sc    74  96  87  85.66
3     Tg    99  83  93  91.66

我们先来看看该如何在 awk 中定义变量与调用变量的值。假设我想统计 PHP 成绩的总分,那么就应该这样:

[root@localhost  ~]$  awk  'NR==2{php1=$3}
NR==3{php2=$3}
NR==4{php3=$3;totle=php1+php2+php3;
print  "totle  php  is  "  totle}'  student.txt
统计 PHP 成绩的总分

我们解释下这个命令。“NR==2{php1=$3}”(条件是 NR==2,动作是 php1=$3)这句话是指如果输 入 数 据 是 第 二 行 ( 第 一 行 是 标 题 行 ) , 就 把 第 二 行 的 第 三 字 段 的 值 赋 予 变 量 “ php1 ” 。“NR==3 { php2=$3;} ”这句话是指如果输入数据是第三行,就把第三行的第三字段的值赋予变量“php2”。
“NR==4{php3=$3;totle=php1+php2+php3;
print "totle php is " totle}”
(“NR==4”是条件,后面{}中的都是动作)这句话是指如果输入数据是第四行,就把第四行的第三字段的值赋予变量“php3”;
然后定义变量 totle 的值是“php1+php2+php3”;然后输出“totle php is”关键字,后面加变量 totle的值。


在 awk 编程中,因为语句非常长,在输入时需要注意以下内容:

  • 多个条件{动作}可以用空格分割,也可以用回车分割。
  • 在一个动作中,如果需要执行多个命令,需要用“;”分割,或用回车分割。
  • 在 awk 中,变量的赋值与调用都不需要加入“$”符。
  • 条件中判断两个值是否相同,请使用“==”,以便和变量赋值进行区分。
在看看该如何实现流程控制,假设如果 Linux 成绩大于 90,就是一个好男人(学 PHP 的表示压力
很大!):
[root@localhost  ~]  awk  '{if  (NR>=2)
{if  ($4>90)  printf  $2  "  is  a  good  man!\n"}}'  student.txt
#程序中有两个 if 判断,第一个判断行号大于 2,第二个判断 Linux 成绩大于 90 分
Liming  is  a  good  man!
Sc  is  a  good  man!

其实在 awk 中 if 判断语句,完全可以直接利用 awk 自带的条件来取代,刚刚的脚本可以改写成这样:

[root@localhost  ~]#  awk  '  NR>=2  {test=$4}
test>90  {printf  $2  "  is  a  good  man!\n"}'  student.txt
#先判断行号如果大于 2,就把第四字段赋予变量 test
#在判断如果 test 的值大于 90 分,就打印好男人
Liming  is  a  good  man!
Sc  is  a  good  man!

7. awk函数

awk 编程也允许在编程时使用函数,在本小节我们讲讲 awk 的自定义函数。awk 函数的定义方法如下:

function  函数名(参数列表){ 函数体 }

我们定义一个简单的函数,使用函数来打印 student.txt 的学员姓名和平均成绩,应该这样来写函数:

[root@localhost  ~]$  awk  'function  test(a,b)  {  printf  a  "\t"  b  "\n"  }
#定义函数 test,包含两个参数,函数体的内容是输出这两个参数的值
{  test($2,$6)  }  '  student.txt
#调用函数 test,并向两个参数传递值。
Name    Average
Liming   87.66
Sc  85.66
Tg  91.66

8. awk中调用脚本

对于小的单行程序来说,将脚本作为命令行自变量传递给 awk 是非常简单的,而对于多行程序就比较难处理。当程序是多行的时候,使用外部脚本是很适合的。首先在外部文件中写好脚本,然后可以使用 awk 的-f 选项,使其读入脚本并且执行。

[root@localhost  ~]$  vi  pass.awk
BEGIN   {FS=":"}
{  print    $1  "\t"    $3}
然后可以使用“-f”选项来调用这个脚本:
[root@localhost  ~]$  awk  -f  pass.awk  /etc/passwd
root    0
bin 1
daemon  2
…省略部分输出…

3. sed命令

sed 主要是用来将数据进行选取、替换、删除、新增的命令,我们看看命令的语法:
[root@localhost ~]# sed [选项] ‘[动作]’ 文件名
选项:
-n: 一般 sed 命令会把所有数据都输出到屏幕,如果加入此选择,则只会把经过 sed 命令处理的行输出到屏幕。
-e: 允许对输入数据应用多条 sed 命令编辑。
-f 脚本文件名: 从 sed 脚本中读入 sed 操作。和 awk 命令的-f 非常类似。
-r: 在 sed 中支持扩展正则表达式。
-i: 用 sed 的修改结果直接修改读取数据的文件,而不是由屏幕输出
动作:
a \: 追加,在当前行后添加一行或多行。添加多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
c \: 行替换,用 c 后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾需用“\”代表数据未完结。
i \: 插入,在当期行前插入一行或多行。插入多行时,除最后 一行外,每行末尾需要用“\”代表数据未完结。
d: 删除,删除指定的行。
p: 打印,输出指定的行。
s: 字串替换,用一个字符串替换另外一个字符串。格式为“行范围 s/ 旧字串/新字串/g”(和 vim 中的替换格式类似)
对 sed 命令大家要注意,sed 所做的修改并不会直接改变文件的内容(如果是用管道符接收的命令的输出,这种情况连文件都没有),而是把修改结果只显示到屏幕上,除非使用“-i”选项才会直接修改文件。

  • 行数据操作
    假设我想查看下 student.txt的第二行,那么就可以利用“p”了:
[root@localhost  ~]#  sed  '2p'  student.txt
ID  Name    PHP Linux   MySQL   Average
1   Liming  82  95  86  87.66
1   Liming  82  95  86  87.66
2   Sc  74  96  87  85.66
3   Tg  99  83  93  91.66

“p”命令确实输出了第二行数据,但是 sed 命令还会把所有数据都输出一次,如果指定输出某行数据,就需要“-n”选项的帮助了:

[root@localhost  ~]#  sed  -n  '2p'  student.txt
1   Liming  82  95  86  87.66
再来看看如何删除文件的数据:
[root@localhost  ~]#  sed  '2,4d'  student.txt
#删除第二行到第四行的数据
ID  Name    PHP Linux   MySQL   Average
[root@localhost  ~]#  cat  student.txt
#但是文件本身并没有修改
ID  Name    PHP Linux   MySQL   Average
1   Liming  82  95  86  87.66
2   Sc  74  96  87  85.66
3   Tg  99  83  93  91.66
再来看看如何追加和插入行数据:
[root@localhost  ~]#  sed  '2a  hello'  student.txt
#在第二行后加入 hello
“a”会在指定行后面追加入数据,想在指定行前面插入数据,则需要使用“i”动作:
[root@localhost  ~]#  sed  '2i  hello  \
>  world'  student.txt
#在第二行前插入两行数据
如果想追加或插入多行数据,除最后一行外,
每行的末尾都要加入“\”代表数据未完结。再来看看“-n”选项的作用:
[root@localhost  ~]#  sed  -n  '2i  hello  \
#只查看 sed 命令操作的数据
>  world'  student.txt
“-n”只查看 sed 命令操作的数据,而不是查看所有数据。
再来看看如何实现行数据替换,
[root@lo  ~]#  cat  student.txt  |  sed  '2c  No  such person'
sed 命令默认情况是不会修改文件内容的,
如果我确定需要让 sed 命令直接处理文件的内容,可以使用“-i”选项。
不过要小心啊,这样非常容易误操作,
在操作系统文件时请小心谨慎。可以使用这样的命令:
[root@localhost  ~]#  sed  -i '2c  No  such  person'  student.txt

相关文章

  • shell编程-2021-07-21

    一、 正则表达式 1.概述 因为用来在文件当中搜索字符串的命令,如 grep、awk、sed等命令可以支持正则表达...

  • shell 案例

    Shell编程一 Shell防范ARP攻击 Shell编程二 Shell防范DDos攻击 Shell编程三 ...

  • shell 第一天

    shell编程初识 1.1 shell编程初识 shell的定义 Shell 是命令解释器 Shell 也是...

  • 78.shell编程

    shell编程 Shell脚本,是一种为shell编写的脚本程序。 Shell编程跟JavaScript、Pyth...

  • 2019-01-25

    Linux系统Shell编程指南 前言 适合人群:有类似C编程基础的人 一、Shell编程介绍 Shell解释型语...

  • day 28

    shell编程基础 shell编程一小时光速入门web集群架构会用到shell编程基础 1、为什么要学shell编...

  • Shell 编程的 Hello World

    什么是 Shell?简单来说,Shell 编程是对 Linux 命令的逻辑化处理。 来看看 Shell 编程是如何...

  • Shell 编程的 Hello World

    什么是 Shell?简单来说,Shell 编程是对 Linux 命令的逻辑化处理。 来看看 Shell 编程是如何...

  • 后端运维人员必备shell编程入门

    本文转载自 公众号 Snailclimb Shell 编程入门 走进 Shell 编程的大门 为什么要学Shell...

  • shell编程

    Shell脚本,是一种为shell编写的脚本程序。 Shell编程跟JavaScript、Python编程一样,只...

网友评论

      本文标题:shell编程-2021-07-21

      本文链接:https://www.haomeiwen.com/subject/jbijmltx.html