抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Sed

sed 是一个面向字符流的编辑器,对文本进行过滤和替换操作,sed 一次仅读取一行进行操作,适合处理大数据文件。可在一个或多个文件上自动实现编辑,简化对多个文件执行相同的编辑处理工作。

sed 默认不修改源文件,仅仅修改输出信息,sed 先将从文件读入的内容放入缓冲区,称为模式空间,在模式空间中对文件的副本操作,再输出到屏幕。

sed [选项]...  [输入文件]...
-n, --quiet, --silent 静默模式,结果不显示到屏幕
-e 脚本 添加脚本指令,可添加多个
-f 脚本文件 添加脚本文件
--follow-symlinks 直接修改文件时跟随软链接
-i[SUFFIX] 直接修改源文件,若指定SUFFIX前缀,则进行对源文件的备份
-l N 指定l命令(输出非打印字符)可输出的行长度
--posix 关闭所有 GNU 扩展
-s, --separate 默认sed将输入的多个文件名当做一个长的输入流,而GNU sed允许看做单独的文件
-u, --unbuffered 从输入文件读取最少的数据,即最低限度的缓存输入和输出

sed 的指令:[地址]指令 内容,在 sed 中/称为定界符,也可用其他的符号作为定界符,如:|等。

  • a:append 追加,若不指定行数,则会在每一行都添加一行内容

    例:sed '2a XXXXX' 文件        在文件的第二行后添加一行内容XXXXX
    sed '/XXX/a XXXXX' 文件 在所有包含XXX的行后添加一行XXXXX
    sed '1,4a XXXXX' 在第1到4行后添加一行XXXXX
    sed '$a XXXXX' 在最后一行后添加一行,$表示最后一行
  • i:insert 插入,是在行添加一行内容,若不指定行数,则在每一行前添加

    例:sed '2i XXXXX' 文件        在第二行前添加一行XXXXX
    sed '/XXX/i XXXXX' 在包含XXX的行前添加一行XXXXX
  • d:delete 删除

    例:sed '2d'        删除第二行
    sed '/^$/d' 删除空白行
    sed '1~2d' ~用于指定从第几行开始的指定步长行的内容
    1~2用于指定第1行开始的两行,即第1,2行
  • s:substitution 替换

    例:sed 's/XXX/XXXX/'   将XXX替换为XXXX,会替换第一个匹配的
    sed 's/XXX/XXXX/n' 只替换第n个匹配的XXX,n的范围是1-512
    sed 's/XXX/XXXX/g' 对模式空间的所有匹配都更改
  • c:替换

    例:sed '/XXX/c XXXXX'   将包含XXX的一行替换为XXXXX
  • p:打印

    例:sed 's/XXX/XXXX/p'   替换后,打印替换后的句子(会重复打印)以及其他未替换的内容
    若和-n一起使用,则只打印进行处理的行
  • n:一遇到匹配的行就立刻移动到下一行

若要执行多个指令,则指令间用逗号分隔,或通过-e 指令1 -e 指令2...指定,最好通过文件添加指令,然后通过-f指定指令文件。

还可使用/XXX/ {指令/内容}替换:匹配的语句支持正则表达式

例:<body>hello<body>
sed 's/body/\/body/2' 将第二个body换为/body,还可用{}实现
sed '/body/ {s//\/body/2}'
就是s/后的要替换的内容提前到前面
还可以用&替换要替换的部分
sed '/body/ {s//\/&/2}'

正则表达式\w\+匹配每一个单词,例:将每个单词都添加一个[] sed 's/\w\+/[&]'

\n匹配子串,n 表示第 n 个子串,用\(XXX\) 匹配子串,会将 XXX 作为主串,将 XXX 后的字符串作为子串,例:将 abcdefg 中的 efg 替换为 fff:sed 's/\(abcd\)efg/\1fff'

可通过在匹配的行间添加逗号选定行范围:sed '/efg/,/abc/'

将指定的内容添加到匹配的行下面:使用a\指令,sed '/abc/a\test',将 test 字符串插入到匹配包含 abc 的行的下面。同理,i\将指定内容添加到匹配的行上面

打印奇数行:sed -n 'p;n'sed -n '1~2p'
打印偶数行:sed -n 'n;p'sed -n '2~2p'

Awk

Awk 是一种模式匹配的程序设计语言,用于对文本和数据进行扫描和处理,常用操作是将数据转换为格式化的报表。常见的 awk 编译器版本有 awk,gawk,gawk 与 awk 一致。

awk 先逐行扫描文件,寻找匹配特定模式的行,并进行操作。因此,awk 基本结构就是由模式匹配处理动作组成。

Shell 编程

三种命令行下运行 shell 脚本的方式:

  • 直接使用bash命令执行,此时 shell 脚本不需要可执行权限,也不需要再第一行指定 shell
  • 添加可执行权限,然后./XXX.sh执行
  • 直接source命令执行

常见系统变量:

  • $HOME:当前用户家目录
  • $IFS:内部字段分隔符
  • $LANG:默认语言
  • $PATH:默认可执行程序路径
  • $PWD:当前目录
  • $UID:当前用户 ID
  • $USER:当前用户
  • $RANDOM:随机生成一个 0-32767 的整数
  • $HOSTNAME:主机名

变量:

  • 普通变量:VAR=value
  • 临时环境变量:export VAR=value

作用域:

  • shell 进程的环境变量作用域为 shell 进程
  • 当 export 导入到系统变量时,作用域变为 shell 进程及其子进程
ps -axjf | grep pts
938 1443 1443 1443 ? -1 Ss 0 0:00 \_ sshd: root@pts/0
1443 1447 1447 1447 pts/0 1497 Ss 0 0:00 | \_ -bash
1447 1497 1497 1447 pts/0 1497 R+ 0 0:00 | \_ ps -axjf
1447 1498 1497 1447 pts/0 1497 S+ 0 0:00 | \_ grep --color=auto pts

第一列:PPID父进程ID
第二列:PID子进程ID

当 ssh 连接 shell 时,当前终端 PPID(-bash)是 sshd 的 PID(root@pts/0),所以当前终端下的所有进程 PPID 都为-bash 的 PID
-bash 下设置的变量,只在-bash 进程下有效,而在-bash 的子进程中无效,只有export 后才能生效。所以在当前 shell 定义的变量一定要 export,否则在写脚本时,会引用不到。
退出终端后,所有用户定义的变量都会清除。

位置变量指的是函数或脚本后跟的第 n 个参数。$1-$n,需要注意的是从第 10 个开始要用花括号调用,例如${10}

shift 可对位置变量控制,每执行一次 shift 命令,位置变量个数就会减一,而变量值则提前一位。shift n,可设置向前移动 n 位。

#!/bin/bash
echo "1: $1"
shift
echo "2: $2"
shift
echo "3: $3"

bash test.sh a b c
1: a
2: c
3:

特殊变量:

  • $0 脚本自身名字
  • $? 返回上一条命令是否执行成功,0 为执行成功,非 0 则为执行失败
  • $# 位置参数总数
  • $* 所有的位置参数被看做一个字符串
  • $@ 每个位置参数被看做独立的字符串
  • $$ 当前进程 PID
  • $! 上一条运行后台进程的 PID

变量引用:

  • Shell 中所有变量引用使用$符,后跟变量名。有时个别特殊字符会影响正常引用,那么需要使用${VAR},如$VAR_
  • 若变量名与其他字符串紧碍着,也会误认为是整个变量
  • 将命令结果作为变量值,如 VAR=echo 123VAR=$(echo 123)

在变量赋值时,如果值有空格,Shell 会把空格后面的字符串解释为命令

VAR=1 2 3
-bash: 2: command not found

单引号是告诉 Shell 忽略特殊字符,而双引号则解释特殊符号原有的意义,比如$!

参考资料

Shell 从入门到精通