Linux 个人笔记之三剑客 grep sed awk

零、预

  • bash 的命令行展开 {}

    $ echo file_{1..4}
    file_1 file_2 file_3 file_4
    
    $ echo file_{a..d}
    file_a file_b file_c file_d
    
    $ echo file_{1..5..2} # 打印file_1-5,步长为2
    file_1 file_3 file_5
    
    $ echo file_{01..5..2} # file_01 03 05
    file_01 file_03 file_05
    
  • 正则表达式 Regular Expression,简称为 Regex 或 RegExp。

    由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配的功能。分两类: 基本正则表达式 BRE(^ $ . [] *)扩展正则表达式 ERE(BRE基础上增加了 () {} ? |等)

    • 基本正则表达式 BRE

      ^   # 用于模式最左侧,匹配字符串开始。例: ^he 匹配以 he 开头的行
      $   # 用于模式最右侧,匹配字符串结尾。例:he$ 匹配以 he 结尾的行
      ^$  # 组合符,表示空行
      .   # 匹配一个非换行符的字符,不能匹配空行。如:'gr.p'匹配gr后接一个任意字符,然后是p
      \   # 转义字符,让特殊含义的字符,现出原形,例:\. 代表小数点
      *   # 匹配前一个字符(连续出现)0次或1次以上,重复0次代表空,即匹配所有内容。例,ab*c 可以匹配字符串**ac**、abc、abbc、abbbc等
      .*  # 组合符,匹配所有内容
      ^.* # 组合符,匹配以任意多个字符开头的内容
      .*$ # 组合符,匹配以任意多个字符结尾的内容
      [abc]  # 匹配[abc]集合内的任意一个字符。[a-c] 如'[Ghg]rep' 匹配Grep、grep、hrep 
      [^abc] # 匹配除了^后面的任意字符,a或b或c,^表示对[abc]的取反
      
    • 扩展正则表达式 ERE grep -E egrep

      ?     # 匹配前面的元素零次或一次
      +     # 匹配前面的元素一次或多次
      [:/]+ # 匹配括号内的:或者/字符一次或多次
      ()    # 小括号的功能之一是分组过滤被括起来的内容,括号内的内容表示一个整体 # egrep 'g(oo|la)d' 1.txt # 匹配good 和 glad
      {n}   # 匹配前面的元素恰好 n 次。
      {n,}  # 匹配前面的元素至少 n 次。
      {n,m} # 匹配前面的元素至少 n 次,但不超过 m 次。
      {,m}  # 匹配前一个字符最多m次
      |     # 用于在模式中创建选择,匹配两者之一
      
      [12345]{2} # 匹配方括号内的任意两个字符
      
    • 二者容易混淆点对比

      .   # 匹配一个非换行符的字符,不能匹配空行
      *   # 匹配【前面的元素】零次或一次以上
      
      ?   # 匹配【前面的元素】零次或一次
      +   # 匹配【前面的元素】至少一次
      
    # 匹配单字符开头包名的 bag 包,匹配包名中 2023-03-15-20-3.*.bag 或者 2023-03-15-20-4.*.bag,并计算行数 即符合条件的包数
    ls -rth | grep -E '^._2023-03-15-20-(3|4).*.bag' | wc -l
    

一、grep 文本过滤工具

基础篇

  • grep(Global search REgular expression(RE) and Print out the line,全面搜索正则表达式并把行打印出来),其功能是从文本文件或管道数据流中筛选匹配的行及数据。 grep [options] [pattern] [file...]

  • 命令选项

    -c # 打印匹配的文本行的行数
    -v # 不包括,反向查找
    -i # 忽略字母大小写
    -o # 仅显示匹配到的字符串本身
    -n # 列出所有匹配的文本行,并显示行号
    -w # 匹配整个单词
    -E # 表示过滤 多个参数 cat 1.txt | grep -E 'SSID|Signal'
    -a # 可将二进制视为文本文件搜寻,相当于--binary-files=text这个参数。
    -l # 输出含匹配项的文件名 grep -l hello *
    -r # 递归的在目录中搜索文本 grep -r "hello" directory
    -m num # --max-count=num 最大匹配次数
    
    # grep -A -B -C(大写)    后面都跟阿拉伯数字 
    -A # 是显示匹配后和它后面的n行。after
    -B # 是显示匹配行和它前面的n行。 before
    -C # 是匹配行和它前后各n行。 context
    
    --exclude
    --exclude-dir
    
    grep -n "hallo" --exclude=heha.txt *
    

实战篇

测试使用的文本内容如下,文件目录为 test/test.txt

hello world
Hello world
HelloWorld
he llo wor ld
hallo
haha
good
glad
  • 实例一:匹配 test.txt 文件中 hello 的个数,以及 hello 忽略大小写的个数。 -c

    # 匹配hello个数
    $ grep -c "hello" test.txt
    1
    ------------------------------------
    # 匹配忽略hello大小写的个数
    $ grep -i -c "hello" test.txt # grep -ic "hello" test.txt
    3
    
  • 实例二:匹配 test.txt 文件中包含 hello(忽略大小写) 的行,并打印行号。 -i -n

    $ grep -i -n "hello" test.txt
    1:hello world
    2:Hello world
    3:HelloWorld
    
  • 实例三:匹配 test.txt 文件中 hello (忽略大小写,匹配整个单词)的行。 -i -w -n

    $ grep -iwn "hello" test.txt
    1:hello world
    2:Hello world
    
  • 实例四:反向查找,匹配 test.txt 文件中不包含 hello (忽略大小写,匹配整个单词)的行。 -i -w -n -v

    $ grep -iwnv "hello" test.txt
    3:HelloWorld
    4:he llo wor ld
    5:hallo
    6:haha
    7:good
    8:glad
    
  • 实例五:过滤多个参数 hello 或者 hallo。 -E

    $ grep -E "hello|hallo" test.txt
    hello world
    hallo
    
  • 实例六:使用 [] 实现实例五的效果。(可以不加 -E)

    $ grep "h[ea]llo" test.txt
    hello world
    hallo
    
  • 实例七:使用 () 实现实例五的效果。(必须加 -E)

    $ grep -E "h(e|a)llo" test.txt
    hello world
    hallo
    
    -----------------------------
    $ grep -E "g(oo|la)d" test.txt
    good
    glad
    
  • 实例八:使用 . 匹配任意字符 h.llo

    $ grep "h.llo" test.txt
    hello world
    hallo
    
    # 以h开头 o结尾的五个字符的行
    $ grep "h...o" test.txt
    
  • 实例九:匹配以 he 开头的行。 ^

    $ grep -n "^he" test.txt
    1:hello world
    4:he llo wor ld
    
  • 实例十:匹配以 ld 结尾的行。 $

    $ grep -n "ld$" test.txt
    1:hello world
    2:Hello world
    3:HelloWorld
    4:he llo wor ld
    ---------------------------
    $ grep -nw "ld$" test.txt
    4:he llo wor ld
    
  • 实例十一:打印匹配 hallo 的相邻行。 ABC

    # hallo 以及后一行
    $ grep -n -A 1 "hallo" test.txt
    5:hallo
    6-haha
    
    # hallo 以及前一行
    $ grep -n -B 1 "hallo" test.txt
    4-he llo wor ld
    5:hallo
    
    # hallo 以及前后各一行
    $ grep -n -C 1 "hallo" test.txt
    4-he llo wor ld
    5:hallo
    6-haha
    
    $ grep -n -1 "hallo" test.txt
    4-he llo wor ld
    5:hallo
    6-haha
    
  • 实例十二:查找包含 hallo 字段的文件名。 -l 可与管道和 xargs 联合使用,删除文件等。

    $ grep -l "hallo" test/* # test文件夹下所有文件,针对的是文件 所以需要加*
    test.txt
    
    # 删除包含 hallo 的文件
    $ grep -l "hallo" test/* | xargs rm
    
  • 实例十三:递归查找 test 文件夹下包含 hallo 字段的文件名。 -r/-R

    $ grep -r -l "hallo" test
    test/test.txt
    
  • 实例十四:匹配 test 文件夹下带 hehe 的文件名,并将其删除。

    $ find test -type f -name "*hehe*" -exec rm {} +
    $ find test -type f -name "*hehe*" -delete
    $ ls test/* | grep hehe | xargs rm
    
    $ ls test/* | grep hehe | xargs rm # 注意test/后必须加*,否则不带test/目录
    
    $ ls test/* | grep hehe
    test/hehe.txt
    
    $ ls test | grep hehe
    hehe.txt
    
  • 实例十五:使用正则表达式查找 a-h 的字母

    grep "[a-h]" test.txt
    cat test.txt| grep "[a-h]"
    
  • 实例十六:使用正则表达式 + ? . *

    $ cat 2.log
    sesesese
    se
    seeeeeeeee
    eeeeee
    soooooooo
    +se+se+
    
    ------------------
    # .:匹配单个非换行符字符 BRE
    # *:零次或多次匹配前面的字符或子表达式 BRE
    # +:一次或多次匹配前面的字符或子表达式 ERE
    # ?:零次或一次匹配前面的字符或子表达式 ERE
    
    # 基本正则表达式中 + 没有特殊含义,以下语句表示匹配 se+ 字符串
    $ grep "se+" 2.log
    +se+se+
    
    # 基本正则表达式中的 \+ 匹配其前面的字符至少1次 (非贪婪模式) 貌似是与egrep的 + 等效的
    $ grep "se\+" 2.log
    sesesese
    se
    seeeeeeeee
    +se+se+
    
    $ grep "se\?" 2.log
    sesesese
    se
    seeeeeeeee
    soooooooo
    +se+se+
    
    $ grep "se." 2.log
    sesesese
    seeeeeeeee
    +se+se+
    
    $ grep "se.*" 2.log
    sesesese
    se
    seeeeeeeee
    +se+se+
    
    $ grep "se*" 2.log
    sesesese
    se
    seeeeeeeee
    soooooooo
    +se+se+
    

二、sed 字符流编辑器

基础篇

  • sed 是 Stream Editor 字符流编辑器的缩写,简称流编辑器。一次处理一行内容,先将一行内容读取到模式空间,处理完成后输出到屏幕,然后清空模式空间,再次读入新的行,并没有直接修改源数据。
  • sed 是操作、过滤和转换文本内容的强大工具。常用功能包括对文件实现快速增删改查(增加、删除、修改、查询),其中查询的功能中最常用的两大功能是过滤(过滤指定字符串)、取行(取出指定行)。
  • sed 以及后面的选项、命令和输入文件,每个元素之间都至少要有一个空格。

在这里插入图片描述

  • 命令选项

    -n # 安静模式,该选项表示sed命令只输出经过编辑的文本行,不输出未编辑的文本行。
    -e # 直接应用 sed 命令,该选项表示sed命令可以接受多个编辑命令,指定要执行的sed命令;
    -r # 扩展正则表达式
    -i # 直接修改读取行内容,该选项表示sed命令直接修改原始文件而不是输出到标准输出流。
    -f # 输出到指定文件中
    -s # 该选项表示sed命令可以将多个空格或制表符替换为单个空格。
    
sed '2a 111' test.txt       # 在test.txt 文件第二行后添加 111,文件内容不变
sed '2i 111' test.txt       # 在test.txt 文件第二行前插入 111,文件内容不变
sed '2d' a.txt              # 删除第二行,文件内容不变
sed '2,5d' a.txt            # 删除2-5行打印,文件内容不变的
sed '/hello/d' a.txt        # 删除a.txt 中包含hello的行
sed '/hello/p' a.txt        # 打印a.txt中包含hello的行
sed -n '2p' test.txt        # 类似查询功能,打印test.txt第二行内容,-n 取消默认输出,只输出匹配行文本
sed -n '2,3p' test.txt 

sed 's/111/aaa/g' test.txt  # g全局替换test.txt中的111为aaa,文件内容不变
sed 's/444/123/' a.txt      # 替换a.txt中的444为123(只会替换每一行中第一次出现的)
sed -n 's/444/123/' a.txt   # 安静模式替换a.txt中的444为123,不打印,不修改内容
sed -n 's/111/444/p' a.txt  # 加参数p进行打印
sed 's/444/666 &/' a.txt    # 444前拼接666

sed -e 's/hello/haha/g' -e '/Hello/d' test.txt 等同于 sed 's/hello/haha/g;/Hello/d' test.txt
  • sed -rn '/^[ \t]*$/!s#^[ \t]*##gp' tt2.txt 删除开头的空格和TAB键

实战篇

测试使用的文本内容如下,文件为 test/test.txt

hello world
Hello world
HelloWorld
he llo wor ld
hallo
haha
good
glad
  • 实例一:删除操作 d

    # 删除包含 hello 的行,-i 修改文件
    $ sed '/hello/d' test.txt
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 删除不包含 hello 的行
    $ sed '/hello/!d' test.txt
    hello world
    
    # 删除 test.txt 所有行
    $ sed 'd' test.txt
    
    # 删除 test.txt 最后一行
    $ sed '$d' test.txt
    hello world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    
    # 删除所有空行
    $ sed '/^$/d' test.txt
    
    # 删除1-3行
    $ sed '1,3d' test.txt
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 删除第一行、第三行
    $ sed '1d;3d' test.txt
    Hello world
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 删除所有的 hello
    $ sed 's/hello//g' test.txt
     world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 删除从root到ftp之间的行
    $ sed '/^root/,/^ftp/d' 1.log
    
    # 删除#开头行和空行
    $ sed '/^#/d;/^$/d' 1.log
    
  • 实例二:新增操作 a i

    # 第二行后添加一行,内容 666
    $ sed '2a 666' test.txt
    hello world
    Hello world
    666
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 第二行前添加一行,内容 666
    $ sed '2i 666' test.txt
    hello world
    666
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 在hello开头的行的下一行添加 666
    $ sed '/^hello/a666' test.txt
    hello world
    666
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    $ sed '/world$/a666' test.txt
    hello world
    666
    Hello world
    666
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 前三行头添加@
    $ sed '1,3s/^/@/' 1.log
    
  • 实例三:替换操作 s

    # 将文件中【每行匹配到的第一个】 hello 替换为 new
    $ sed 's/hello/new/' test.txt
    new world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 将文件中【所有匹配到】的 hello 替换为 new
    $ sed 's/hello/new/g' test.txt
    new world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 将文件中【所有匹配到】的 hello(I 忽略大小写) 替换为 new
    $ sed 's/hello/haha/gI' uniq.txt
    haha world
    haha world
    good day
    who are you
    haha world
    haha world
    good
    
    # 将3-4行匹配到的 Hello 替换为 new
    $ sed '3,4s/Hello/new/g' test.txt
    hello world
    Hello world
    newWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 注释所有代码
    $ sed 's/^/#/g' test.txt
    # 注释第二行
    $ sed '2s/^/#/g' test.txt
    hello world
    #Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 将所有的 hello 替换为 hellos
    $ sed 's/hello/hellos/g' test.txt
    hellos world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    $ sed 's/hello/&s/g' test.txt # & 查找
    hellos world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good
    glad
    
    # 每行行首添加 start,行尾添加 end
    $ sed 's/^/start /; s/$/ end/' test.txt
    start hello world end
    start Hello world end
    start HelloWorld end
    start he llo wor ld end
    start hallo end
    start haha end
    start good end
    start glad end
    
    # good 后拼接 day
    $ sed 's/good/& day/' test.txt
    hello world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    good day
    glad
    
    $ sed 's/good/very &/' test.txt
    hello world
    Hello world
    HelloWorld
    he llo wor ld
    hallo
    haha
    very good
    glad
    # 删除文件中 a-h 的字母
    $ sed 's/[a-h]//g' test.txt
    llo worl
    Hllo worl
    HlloWorl
     llo wor l
    llo
    
    oo
    l
    
    # 替换 echo 打印
    $ echo "12356" | sed 's/[1,3]//g'
    256
    
    # 将passwd.txt文件中的/bin/bash全部替换为/sbin/sh
    $ sed "s/\/bin\/bash/\/sbin\/sh/" passwd.txt
    
  • 实例四:其他

    # 日志中查找报错的日期
    sed -n '/ERROR/p' test.txt | awk '{print $1}'
    

三、awk 文本处理工具

基础篇

  • awk 不仅仅是 Linux 系统中的一个命令,而且其还是一种编程语言,可以用来处理数据和生成报告(Excel)。处理的数据可以是一个或多个文件,它是 Linux 系统最强大的文本处理工具,没有之一。
  • 以换行符为默认记录分隔符,逐一读取记录,以空格为默认域分隔符将每条记录切片,切开的部分再进行后续处理。
  • awk 必须外层单引号,内层双引号。 内置变量 $1 $2 都不得添加双引号,否则会识别为文本,尽量别加引号。
  • 在 awk 中,printprintf 是两个用于输出的关键字,它们有一些区别:
    • print 是一个简单的输出语句,用于打印指定的表达式或变量。
    • 每个 print 语句结束后,默认会追加一个换行符(newline)。
    • printf 是一个格式化输出语句,类似于 C 语言中的 printf 函数。
    • 你可以使用格式说明符来定义输出格式,然后列出要输出的变量或表达式。
    • 不像 printprintf 不会自动添加换行符,你需要显式地在格式字符串中或者用 "\n" 添加换行。
  • awk [option] 'pattern[action]' file ...
    • 常用选项

      -F # 用于指定字段分隔符,以便 AWK 能够正确解释每行中的字段。例如,-F':' 表示使用冒号作为字段分隔符。
      -v # 定义或修改awk内部变量。用于在 AWK 脚本中传递外部变量。例如,-v var=value 将变量 var 设置为指定的值。-v OFS=","
      -f # 从外部文件加载 awk 脚本。 awk -f script.awk file.txt # 执行script.awk 中的 awk脚本
      
    • 常用参数

      FILENAME # awk浏览的文件名
      BEGIN # 处理文本之前要执行的操作,程序开始时候执行,只执行一次
      BODY  # 会循环针对每一行执行命令
      END   # 处理文本之后要执行的操作
      
      FS    # 输入字段分隔符,等价于命令行-F选项,默认为空格
      OFS   # 输出字段分隔符,默认 空格; 通过-v修改。逗号 -v OFS=","
      NF    # Number of Field,当前行的字段个数(列数)
      NR    # Number of Records 行号,当前处理的文本行的行号
      ORS   # 输出记录分隔符(输出换行符)
      RS    # 输入记录分隔符(输入换行符),默认为换行符
      $0    # 整条记录
      $1    # 表示当前行的第一个域....以此类推
      
    • 首先 NR 在 awk 中表示行号(记录号),NR==5 表示行号等于 5 的行。这里需要注意必须使用两个等号,在 awk 中两个等号表示“等于”,一个等号表示赋值,即向一个变量里面放置内容。注意:awk 后面所接的内容要用单引号。 $0 表示一整行内容, $1 表示第一列内容, $NF 表示最后一列。print 关键字表示显示的内容,相当于是 awk 内部的一个命令,需要放在花括号中。

    • awk 的内置变量 NR(行号)、NF(字段号)是不用添加 $ 符号的。取最后一个字段的值 $NF。

实战篇

# awk.txt
left hall hello
right hall hello
hello world
day day up
bad boy
  • 实例一:信息打印

    # 打印第一列信息
    $ awk '{print $1}' awk.txt
    left
    right
    hello
    day
    bad
    
    # 打印行号和第一列信息
    $ awk '{print NR,$1}' awk.txt
    1 left
    2 right
    3 hello
    4 day
    5 bad
    
    # 打印第二行第一列信息,通过这种方式取IP地址
    $ awk 'NR==2{print NR,$1}' awk.txt
    2 right
    
    # 打印第一、二列信息,两列信息空格隔开(注意$1$2之间加空格无效)
    $ awk '{print $1 $2}' awk.txt # {$1 $2} 间空格无效
    lefthall
    righthall
    helloworld
    dayday
    badboy
    
    $ awk '{print $1" "$2}' awk.txt # 双引号空格
    left hall
    right hall
    hello world
    day day
    bad boy
    
    $ awk '{print $1,$2}' awk.txt
    left hall
    right hall
    hello world
    day day
    bad boy
    
    $ awk '{print "n1: ",$1,"n2: ",$2}' awk.txt
    n1:  left n2:  hall
    n1:  right n2:  hall
    n1:  hello n2:  world
    n1:  day n2:  day
    n1:  bad n2:  boy
    
    # 修改输出分隔符,打印第一列第二列信息
    $ awk -v OFS=" ==== " '{print $1,$2}' awk.txt
    left ==== hall
    right ==== hall
    hello ==== world
    day ==== day
    bad ==== boy
    
    # 打印最后一列信息
    $ awk '{print $NF}' awk.txt
    hello
    hello
    world
    up
    boy
    
    # 打印倒数第二列信息
    $ awk '{print $(NF-1)}' awk.txt
    hall
    hall
    hello
    day
    bad
    
    # 格式化打印列信息 printf,- 左对齐
    $ awk '{printf "%s\t%-6s\t%s\n",$1,$2,$3}' awk.txt
    left  hall  	hello
    right hall  	hello
    hello	world
    day	  day   	up
    bad	  boy
    
    # 打印所有行信息
    $ awk '{print $0}' awk.txt
    left hall hello
    right hall hello
    hello world
    day day up
    bad boy
    
    $ awk '{printf "%s\n",$0}' awk.txt
    left hall hello
    right hall hello
    hello world
    day day up
    bad boy
    
    # 打印第二行和第四行内容
    $ awk 'NR==2 || NR==4' awk.txt
    right hall hello
    day day up
    
    # 打印第二行到第四行内容
    $ awk 'NR==2,NR==4' awk.txt
    right hall hello
    hello world
    day day up
    
    $ awk 'NR==2,NR==4{print NR,$0}' awk.txt
    2 right hall hello
    3 hello world
    4 day day up
    
    # 打印3行以内的内容
    $ awk 'NR<3' awk.txt
    left hall hello
    right hall hello
    
    # 打印匹配行
    $ awk '/^hello/{print}' awk.txt
    hello world
    
    $ awk '/^hello/' awk.txt
    hello world
    
    # 打印第一列匹配hello的行,~ 表示包含 !~ 表示不包含
    $ awk -F " " '$1~/hello/{print}' awk.txt
    hello world
    
    $ awk -F " " '$1~/hello/' awk.txt
    hello world
    
  • 实例二:文本分割处理打印

    # 指定空格分隔符,打印
    $ awk -F " " '{print $1}' awk.txt
    left
    right
    hello
    day
    bad
    
    $ awk -v FS=" " '{print $1}' awk.txt
    left
    right
    hello
    day
    bad
    
    # 指定.分隔符
    $ echo "192.168.10.10" | awk -F "." '{print $2}'
    
    # 以空格分隔,打印行号、第一列、最后一列内容。 -F后可用单双引号或者不加引号,但是建议加双引号。
    $ awk -F " " 'NR==2,NR==4 {print NR,$1,$NF}' awk.txt
    2 right hello
    3 hello world
    4 day up
    
    # 每行开头添加###,行尾添加???
    $ awk '{print "###",$0,"???"}' awk.txt
    ### left hall hello ???
    ### right hall hello ???
    ### hello world ???
    ### day day up ???
    ### bad boy ???
    
    # 每行行尾添加???
    $ awk -v ORS=" ???\n" '{print NR,$0}' awk.txt
    1 left hall hello ???
    2 right hall hello ???
    3 hello world ???
    4 day day up ???
    5 bad boy ???
    
    # 文件头插入 start,文件尾添加 end
    $ awk 'BEGIN{print "-------start------"}{print $0}END{print "---------end-------"}' awk.txt
    -------start------
    left hall hello
    right hall hello
    hello world
    day day up
    bad boy
    ---------end-------
    
    # ifconfig 截取IP地址
    $ ifconfig en0
     en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    	options=6463<RXCSUM,TXCSUM,TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM>
    	ether a0:78:17:5e:34:30
    	inet6 fe80::1042:c8ab:2e47:62ea%en0 prefixlen 64 secured scopeid 0xb
    	inet6 fe80::1042:c8ab:2e47:62ea%en0 prefixlen 64 secured scopeid 0xb
    	inet 172.16.176.131 netmask 0xfffff800 broadcast 172.16.183.255
    	nd6 options=201<PERFORMNUD,DAD>
    	media: autoselect
    	status: active
    
    $ ifconfig en0 | awk -F ' ' 'NR==5{print $2}'
    $ ifconfig en0 | sed -n '5p' | awk -F ' ' '{print $2}'
    
  • 实例三:BEGIN 与 数值计算等

    # 指定分隔符为 : ,输出分隔符为 , ,打印第一列和倒数第二列值  OFS=\t
    $ awk -F ":" -v OFS="," '{print $1,$(NF-1)}' awk.txt
    
    # 行号、字段号
    $ awk -F ":" '{print NR,NF,$1}' awk.txt
    
    # 打印文件名和内容
    $ awk '{print FILENAME,$0}' awk.txt
    awk.txt left hall hello
    awk.txt right hall hello
    awk.txt hello world
    awk.txt day day up
    awk.txt bad boy
    
    # 通过-v修改变量值
    $ awk -v name="jack" 'BEGIN{print "my name is : ",name}'
    my name is :  jack
    
    # 数值计算
    $ awk 'BEGIN{sum=0}{sum+=1}END{print sum}' awk.txt # awk.txt 5行
    5
    
    # 数值截取计算
    $ echo "192.168.10.10" | awk -F "." 'BEGIN {sum=1} {sum+=$2} {print sum}'
    169
    
    $ awk 'BEGIN{a=10;b=10; if(a==b) print "a==b"}'
    a==b
    
    $ awk 'BEGIN{print "开始使用awk"} {print $0}' awk.txt
    开始使用awk
    left hall hello
    right hall hello
    hello world
    day day up
    bad boy
    
    $ awk '{print ARGV[0],ARGV[1],ARGV[2]}' awk.txt
    awk awk.txt
    awk awk.txt
    awk awk.txt
    awk awk.txt
    
    $ awk '{print ARGV[0],ARGV[1],ARGV[2]}' awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    awk awk.txt test.txt
    

四、附

xargs

  • (英文全拼: extended arguments)主要用于构建和执行命令行命令,它从标准输入中读取数据,并将其作为参数传递给其他命令。

  • 实例一:匹配文件夹下文件名包含某字段的文件,并将其删除。 ls ./* | grep hello | xargs rm

  • 实例二:匹配文件夹下文件内容包含某字段的文件,并将此文件删除。 grep -l "hello" ./* | xargs rm

  • 实例三:删除指定类型的文件。 ls *.log | xargs rm

  • 实例四:重命名文件。 grep -l "hello" test/* | xargs -I{} mv {} {}.bak -I 用于指定一个占位符来代替从前一个命令接收到的参数。在 -I 后面指定的字符串将用作占位符,用于替换每个从标准输入传递过来的参数。

  • 实例五:写文件。 grep -l "hello" test/* | xargs -I{} sh -c 'echo "hello" >> {}'

  • 实例六:将查找到的文件打包。 ls *.txt | xargs tar -zcvf c.tar.gz find . -type f -name “*.cfg” |xargs tar -zcvf cfg.tar.gz

  • 实例七:将单行或多行文本输入转换为其他格式。

    # 多行变单行
    cat test.txt | xargs
    
    # 单行变多行
    cat 1.txt |xargs -n3 # 3列
    

uniq & sort

基础篇

  • uniq 用于去除相邻重复的行。如果需要去重前先排序,通常与 sort 结合使用。

    -d  # 仅显示重复的行
    -u  # 仅显示不重复的行
    -c  # 在每行前面显示该行在文件中出现的次数
    -i  # 比较行时忽略大小写
    
  • sort 命令的作用是将指定的字段、文件的内容进行排序,并且将排序的结果输出。

  • sort 既可以从文件内的数据进行读取,也可以通过 stdin 标准输出从键盘读取,也可以读取命令执行后获取的字段。

    -f   # 忽略大小写
    -b   # 忽略每行前导的空格字符,进行排序。
    -r   # 以逆序(降序)排列。
    -n   # 按照数字大小进行排序。
    -k   # 指定按照第几个字段进行排序。例如,-k2 表示按照第二个字段排序。
    -t   # 指定字段分隔符,默认是空格。例如,-t':' 表示使用冒号作为字段分隔符。
    -u   # 去除相邻的重复行。
    -o   # 将排序后的结果输出到指定文件,而不是打印到终端。 sort -o output.txt input.txt
    

实战篇

# uniq.txt
hello world
hello world
good day
who are you
hello world
Hello world
good
  • 实例一:uniq

    # 显示重复行
    $ uniq -d uniq.txt
    hello world
    
    # 显示不重复行
    $ uniq -u uniq.txt
    good day
    who are you
    hello world
    Hello world
    good
    
    # -d -c # 显示重复行,以及重复的次数。其实hello world 有三个,但uniq仅统计相邻行
    $ uniq -d -c uniq.txt
       2 hello world
    # -i 忽略大小写
    $ uniq -d -c -i uniq.txt
       2 hello world
       2 hello world
    
  • 实例二:sort 内容排序

    $ sort uniq.txt
    Hello world
    good
    good day
    hello world
    hello world
    hello world
    who are you
    
    # -f 忽略大小写 -r 逆向排序
    $ sort -f -r uniq.txt
    who are you
    hello world
    hello world
    hello world
    Hello world
    good day
    good
    $ cat uniq.txt | sort -f -r
    who are you
    hello world
    hello world
    hello world
    Hello world
    good day
    good
    
    # -f 忽略大小写 -u 去除相邻行排序
    $ sort -u -f uniq.txt
    good
    good day
    hello world
    who are you
    
  • 实例三:sort 和 uniq 组合使用

    # 排序统计次数
    $ sort uniq.txt | uniq -c
       1 Hello world
       1 good
       1 good day
       3 hello world
       1 who are you
    
    # 忽略大小写sort后uniq
    $ sort -f uniq.txt | uniq -c -i
       1 good
       1 good day
       4 Hello world
       1 who are you
    

cut

  • 用于从文本文件或标准输入中剪切指定范围的文本。
  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值