欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

马哥 06_02 _sed命令 有大用

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个参数给脚本,参数均为用户名,将此用户的

image.png




sed  后面 双引号,单引号都成,如果里面有变量的话 用双引号




[root@ebs-22618 ~]# cat /etc/fstab

image.png






image.png



image.png

image.png

image.png



image.png


image.png



[root@ebs-22618 ~]# cat /etc/fstab

image.png

[root@ebs-22618 ~]# sed '1,2d' /etc/fstab ( 这里d表示删除,处理完成之后默认是把模式空间中的内容显示出来,)

image.png


[root@ebs-22618 ~]# sed '3,$d' /etc/fstab   (只要没有变量,单引号,引号都可以 单双引号都可以)image.png


[root@ebs-22618 ~]# cat /etc/fstab

image.png

[root@ebs-22618 ~]# sed '/default/d' /etc/fstab  只要包含 default 模式的就删除

image.png


[root@ebs-22618 ~]# sed '1,+2d' /etc/fstab

image.png



[root@ebs-22618 ~]# sed '1d' /etc/fstab 只删第1行

image.png


[root@ebs-22618 ~]# sed '/^\//d' /etc/fstab 删除斜线开头的行 (只要跟元字符冲突,就要加反斜线,表示字符本身的意义)

image.png



[root@ebs-22618 ~]# sed '/^\//p' /etc/fstab

image.png



[root@ebs-22618 ~]# sed -n '/^\//p' /etc/fstab

image.png


[root@ebs-22618 ~]# sed -n '/^\//p' /etc/fstab

image.png


[root@ebs-22618 ~]# sed '/^\//a \# hello world' /etc/fstab

image.png

[root@ebs-22618 ~]# sed '/^\//a \"# hello world"' /etc/fstab

image.png




[root@ebs-22618 ~]# sed '/^\//a \# hello world\n #hello linux' /etc/fstab       \n 换行

image.png


[root@ebs-22618 ~]# cat /etc/issue

image.png

[root@ebs-22618 ~]# sed '2r /etc/issue' /etc/fstab  (在第2行的后面读取/etc/issue添加第2行的后面 )

image.png



[root@ebs-22618 ~]# cat /etc/issue

image.png

[root@ebs-22618 ~]# sed '$r /etc/issue' /etc/fstab  与cat 显示两个连续文件的效果是一样的

image.png


[root@ebs-22618 ~]# sed '1,2r /etc/issue' /etc/fstab  (第一行后面添加显示,第二行后面也添加显示)

image.png


[root@ebs-22618 ~]# sed '/default/w /tmp.default.txt' /etc/fstab

image.png

[root@ebs-22618 ~]# cat /tmp.default.txt

image.png

[root@ebs-22618 ~]# sed -n '/default/w /tmp.default.txt' /etc/fstab    -n 此时不会显示image.png




[root@ebs-22618 ~]# sed '1,$'   表示全文  全文可以不写


[root@ebs-22618 ~]# sed 's/default/DEFAULT/' /etc/fstab

 image.png


[root@ebs-22618 ~]# sed 's/^\//#/' /etc/fstab

image.png



[root@ebs-22618 ~]# sed 's/\//#/' /etc/fstab  正常情况下只替换每一行中的第一个

image.png


[root@ebs-22618 ~]# sed 's/\//#/g' /etc/fstab  此时由于有修饰符,所以全部替换为#


image.png



[root@ebs-22618 ~]# sed 's@/@#@g' /etc/fstab  由于被替换来替换有 / 和  # 所以分隔符使用@ 这样就不用加反斜杠了

image.png



[root@ebs-22618 ~]# nano sed.txt

image.png


[root@ebs-22618 ~]# sed 's#l..e#l..er#' sed.txt  这样不对 后面的点当作字符了

image.png


[root@ebs-22618 ~]# sed 's#l..e#&r#' sed.txt 可以不用括号括起来,后面用与符号&代指前面

image.png


[root@ebs-22618 ~]# sed 's#\(l..e\)#\1r#' sed.txt      \1 作用与上面的&一样

image.png




[root@ebs-22618 ~]# sed 's#l\(..e\)#L\1#' sed.txt   这是把l..e 变成 L..e的形式 ,小l就成大L

image.png


[root@ebs-22618 ~]# history | more

image.png


[root@ebs-22618 ~]# history | sed 's#[[:space:]]##g' 

image.png



[root@ebs-22618 ~]# history | sed 's#^[[:space:]]*##g'   为什么星号*改成加号+不行(因为 + 属于扩展的正则表达式 假如使用+的话 那么 history | sed -r 's/^[[:space:]]+//'   )  (-r 表示的是使用扩展的正则表达式)

image.png


[root@ebs-22618 ~]# history | sed 's#^[[:space:]]*##g' | cut -d' ' -f1 | more

image.png



 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 选项,即使只执行一个命令。



普通分类: