欢迎各位兄弟 发布技术文章
这里的技术是共享的
grep , sed(流程辑器), awk(报告文本生成器)
sed基本用法
sed: Stream EDitor
字处理器和文本编辑器是两码事,sed是文本编辑器
行编辑器 逐行处理acsii 文本的
(全屏编辑器: vi 入门很难,学会了后发现功能异常强大,这点与nano不同)
sed 并不处理文本文件本身 它逐行读取,读到内存,在内存中完成编辑,并后把编辑的结果输出到屏幕上来
对sed 而言 这段内存空间称为 模式空间 ,因为sed 并不是每一行都处理的,它可以指定仅处理哪些行,这些行可以像glob一样做模式过滤的,符合模式条件的一律处理,不符合条件就不处理
还有保留空间,回头再说
sed 在处理每个文件,把符合模式条件的行读进模式空间来作匹配(或者说把每一行读进模式空间,跟我们的模式进行匹配),如果被模式条件匹配到了,就在模式空间中使用后面的编辑命令对其完成编辑,并且将编辑的结果输出到屏幕上来
sed : 模式空间
默认不编辑原文件,仅对模式空间中的数据做处理;而后,处理结束后,默认将模式空间打印到屏幕
sed [options] ' AddressCommand[额外的修饰符]' file ... (AddressCommand之间没有空格 Commond 是子命令,file文件可以有多个)
Address 指的是哪些行
不同的Commond 使用格式是不一样的
还有修饰符 以后再说
AddressCommond 之间没有空格,它们之间不需要空白字符的,直接写就成
对这些文件中的符合地址范围内的行执行一下编辑命令
sed [option] 'AddressCommond' file.....
-n:--quiet, --silent静默模式 不再显示模式空间的内容(命令让它处理什么它就显示什么)
-n, --quiet, --silent
suppress automatic printing of pattern space
-i: --in-place直接修改原文件 (这个很危险,需谨慎)
-e SCRIPT -e SCRIPT: --expression可以同时执行多个脚本 (把'AddressCommond' 称作脚本)
见最下面 sed -e 与 不加 -e 的区别 示例
sed '/rocommunity.*127\.0\.0\.1/p;/rocommunity/d' /path/to/input (这个是不是相当于-e)
$ sed -n -e '/rocommunity.*127.0.0.1/p' -e '/rocommunity/!p' data.in >data.out
-f /PATH/TO/SED_SCRIPT:(--file) (把'AddressCommond' 保存到文件中 ,应该是一行一行的,每一行一个脚本)
sed -f /path/to/scripts file (把每个SCRIPT一行保存到这个script文件当中)
-r :--regexp-extended使用扩展的正则表达式 (默认情况下,使用基本的正则表达式)
-n, --quiet, --silent
suppress automatic printing of pattern space
-e script, --expression=script
add the script to the commands to be executed
-f script-file, --file=script-file
add the contents of script-file to the commands to be executed
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if extension supplied)
-c, --copy
use copy instead of rename when shuffling files in -i mode
(avoids change of input file ownership)
-l N, --line-length=N
specify the desired line-wrap length for the ‘l’ command
--posix
disable all GNU extensions.
-r, --regexp-extended
use extended regular expressions in the script.
-s, --separate
consider files as separate rather than as a single continuous
long stream.
-u, --unbuffered
load minimal amounts of data from the input files and flush the
output buffers more often
Address:
1,StartLine,EndLine
比如1,100 从第一行到100行
$: 最后一行 (这不是正则表达式,不需要用//)
$-1:倒数第二行 (这不是正则表达式,不需要用//) (好像这样子不行)
2,/RegExp/ (/Pattern/) (正则表达式)使用正则表达式指定的模式
比如 /^root/ 以root 开头的行
3, /pattern1/,/pattern2/ 表示第一次被/pattern1/ 匹配到的行开始到第一次/pattern2/匹配到的行结束中间的所有的行
4,只给一个数值 LineNumber 只指定一行(或起始行,表示精确匹配某行)
5,指定超始行 StartLine,+N 从 startLine开始向后的N行 (一共就是n+1行(包括起始行))
Command:
d:(delete)删除符合条件的行 意味着被匹配到的反而不显示,没删除的反而显示出来
p:(print)显示符合条件的行 /p (print)
a \"string": (append)在指定的行后面 追加新行,内容为"string" (如果有空格,一般说来,string要加双引号引起来,经测试应该不加引号也行)
\n 可以用于换行
i \"string": (insert)在指定的行前面 添加新行,内容为"string" (如果有空格,一般说来,string要加引号引起来,经测试应该不加引号也行)
r FILE:(read)将指定的文件的内容添加至符合条件的行后
r filename (小R表示读整个文件的添加进来)
Append text read from filename.
R filename (大R表示只读文件的第一行添加进来)
Append a line read from filename.
w FILE:(write)将地址指定范围内的行另存至指定的文件中
s/pattern/string/修饰符: (search)查找并替换 在行中查找出 pattern 字符串替换为string字符串 默认只替换每行中第一次被匹配到的字符串
加修饰符(替换标记)
g:(global)全局替换
i:(ignore) 查找时忽略字符大小写
s///, s###, s@@@ 分隔符也可以, 如果是井号分隔符,再找斜线就不用转义了
其实很多字符都可以用作分隔符
\(\) \1 \2 反向引用 应该叫后向引用吧
l..e : like->liker
love->lover
&:与符号表示模式匹配到的整个串
like->Like
love->Love
此时只能用后向引用 不能用与符号&
sed练习:
1,删除 /etc/grub.conf文件中行首的空白符 空格
[root@ebs-22618 ~]# sed 's/^[[:space:]]*//' /etc/grub.conf
2,替换 /etc/inittab文件中 "id:3:initdefault:" 一行中的数字为5
[root@ebs-22618 ~]# sed 's/\(id:\)\([0-9]*\)\(:initdefault\)/\15\3/' /etc/inittab
3,删除/etc/inittab文件中的空白行
[root@ebs-22618 ~]# sed '/^$/d' /tmp/inittabtmp
4,删除/etc/inittab文件中开头的#号
[root@ebs-22618 ~]# sed 's/^#//' /etc/inittab
5,删除/etc/inittab文件中开头的#号及后面的空白字符,但要求#号后面必须有空白字符
sed -r 's/^#[[:space:]]+//' /tmp/inittabtmp
6,删除某文件中以空白字符后面跟#号的行中的开头的空白字符及#号
[root@ebs-22618 ~]# sed -r 's/^[[:space:]]+#//' test100.txt
vi test100.txt
示例
#abc
# hello world
# hi world
7,取出一个文件路径的目录名称
路径如 /etc/aaa/bbbb,/etc/aaa/ 是正确的 但是 /etc 就不对了
[root@ebs-22618 ~]# echo "/ect/aaa/bbbb" | sed -r 's@^(/.*/)[^/]+/?@\1@'
练习:
传递一个用户名参数给脚本,判断此用户的用户名跟其基本组的组名是否一致,并将结果显示出来
练习:
传递三个参数给脚本,第一个为整数,第二个为算术运算符,第三个为整数,将计算结果显示出来 要求保留两位精度,形如:
./calc.sh 5 / 2
练习:
传递3个参数给脚本,参数均为用户名,将此用户的
sed 后面 双引号,单引号都成,如果里面有变量的话 用双引号
[root@ebs-22618 ~]# cat /etc/fstab
[root@ebs-22618 ~]# cat /etc/fstab
[root@ebs-22618 ~]# sed '1,2d' /etc/fstab ( 这里d表示删除,处理完成之后默认是把模式空间中的内容显示出来,)
[root@ebs-22618 ~]# sed '3,$d' /etc/fstab (只要没有变量,单引号,引号都可以 单双引号都可以)
[root@ebs-22618 ~]# cat /etc/fstab
[root@ebs-22618 ~]# sed '/default/d' /etc/fstab 只要包含 default 模式的就删除
[root@ebs-22618 ~]# sed '1,+2d' /etc/fstab
[root@ebs-22618 ~]# sed '1d' /etc/fstab 只删第1行
[root@ebs-22618 ~]# sed '/^\//d' /etc/fstab 删除斜线开头的行 (只要跟元字符冲突,就要加反斜线,表示字符本身的意义)
[root@ebs-22618 ~]# sed '/^\//p' /etc/fstab
[root@ebs-22618 ~]# sed -n '/^\//p' /etc/fstab
[root@ebs-22618 ~]# sed -n '/^\//p' /etc/fstab
[root@ebs-22618 ~]# sed '/^\//a \# hello world' /etc/fstab
[root@ebs-22618 ~]# sed '/^\//a \"# hello world"' /etc/fstab
[root@ebs-22618 ~]# sed '/^\//a \# hello world\n #hello linux' /etc/fstab \n 换行
[root@ebs-22618 ~]# cat /etc/issue
[root@ebs-22618 ~]# sed '2r /etc/issue' /etc/fstab (在第2行的后面读取/etc/issue添加第2行的后面 )
[root@ebs-22618 ~]# cat /etc/issue
[root@ebs-22618 ~]# sed '$r /etc/issue' /etc/fstab 与cat 显示两个连续文件的效果是一样的
[root@ebs-22618 ~]# sed '1,2r /etc/issue' /etc/fstab (第一行后面添加显示,第二行后面也添加显示)
[root@ebs-22618 ~]# sed '/default/w /tmp.default.txt' /etc/fstab
[root@ebs-22618 ~]# cat /tmp.default.txt
[root@ebs-22618 ~]# sed -n '/default/w /tmp.default.txt' /etc/fstab -n 此时不会显示
[root@ebs-22618 ~]# sed '1,$' 表示全文 全文可以不写
[root@ebs-22618 ~]# sed 's/default/DEFAULT/' /etc/fstab
[root@ebs-22618 ~]# sed 's/^\//#/' /etc/fstab
[root@ebs-22618 ~]# sed 's/\//#/' /etc/fstab 正常情况下只替换每一行中的第一个
[root@ebs-22618 ~]# sed 's/\//#/g' /etc/fstab 此时由于有修饰符,所以全部替换为#
[root@ebs-22618 ~]# sed 's@/@#@g' /etc/fstab 由于被替换来替换有 / 和 # 所以分隔符使用@ 这样就不用加反斜杠了
[root@ebs-22618 ~]# nano sed.txt
[root@ebs-22618 ~]# sed 's#l..e#l..er#' sed.txt 这样不对 后面的点当作字符了
[root@ebs-22618 ~]# sed 's#l..e#&r#' sed.txt 可以不用括号括起来,后面用与符号&代指前面
[root@ebs-22618 ~]# sed 's#\(l..e\)#\1r#' sed.txt \1 作用与上面的&一样
[root@ebs-22618 ~]# sed 's#l\(..e\)#L\1#' sed.txt 这是把l..e 变成 L..e的形式 ,小l就成大L
[root@ebs-22618 ~]# history | more
[root@ebs-22618 ~]# history | sed 's#[[:space:]]##g'
[root@ebs-22618 ~]# history | sed 's#^[[:space:]]*##g' 为什么星号*改成加号+不行(因为 + 属于扩展的正则表达式 假如使用+的话 那么 history | sed -r 's/^[[:space:]]+//' ) (-r 表示的是使用扩展的正则表达式)
[root@ebs-22618 ~]# history | sed 's#^[[:space:]]*##g' | cut -d' ' -f1 | more
sed -e 与 不加 -e 的区别 示例
sed
是一个流编辑器,用于对输入流(或文件)进行基本的文本转换。-e
选项用于指定要执行的 sed
命令脚本。
使用 -e
选项
当使用 -e
选项时,你可以明确地为 sed
指定一个或多个命令脚本。这对于一次执行多个 sed
命令非常有用。
示例:
bash复制代码echo "Hello World" | sed -e 's/Hello/Hi/' -e 's/World/Universe/'
输出:
复制代码Hi Universe
在这个例子中,我们使用了两个 -e
选项来指定两个替换命令。第一个命令将 "Hello" 替换为 "Hi",第二个命令将 "World" 替换为 "Universe"。
不使用 -e
选项
如果你只执行一个 sed
命令,那么通常不需要 -e
选项。你可以直接将命令放在 sed
之后。
示例:
bash复制代码echo "Hello World" | sed 's/Hello/Hi/'
输出:
复制代码Hi World
在这个例子中,我们只执行了一个替换命令,所以不需要 -e
选项。
总结
使用 -e
选项可以让你在单个 sed
命令中执行多个命令脚本。
如果你只执行一个 sed
命令,那么通常不需要 -e
选项。
然而,需要注意的是,即使你只执行一个命令,使用 -e
也是完全有效的,并且有时为了代码的一致性和清晰度,程序员可能会选择始终使用 -e
选项,即使只执行一个命令。