文本操作

sed、awk、grep,这也是linux命令过滤转换输出最精华的三条命令

三剑客之一 grep/egrep

语法: grep [-cinvABC] ‘word’ filename

-c :打印符合要求的行数
-n :在输出符合要求的行的同时连同行号一起输出
-v :打印不符合要求的行(就相当于取反输出)
-A :后跟一个数字(有无空格都可以),例如 –A2则表示打印符合要求的行以及下面两行 -B :后跟一个数字,例如 –B2 则表示打印符合要求的行以及上面两行
-C :后跟一个数字,例如 –C2 则表示打印符合要求的行以及上下各两行
-r : 会把目录下面所有的文件全部遍历
-w : 精确匹配

例子介绍

# 过滤出带有某个关键词的行并输出行号 ----- 
grep -n 'root' 1.txt 
# 过滤出不带有某个关键词的行并输出行号 ----- 
grep -n -v 'root' 1.txt
# 过滤出所有包含数字的行 ----- 
grep '[0-9]' 1.txt
# 过滤出所有不包含数字的行 ----- 
grep -v '[0-9]' 1.txt
# 去除所有以'#'开头的行 
grep ----- -v '^#' 1.txt
# 去除所有空行和以'#'开头的行 ----- 
grep -v '^$' 1.txt|grep -v '^#'
# 过滤出以英文字母开头的行 ----- 
grep '^[a-zA-Z]' 1.txt
# 过滤出以非数字开头的行 ----- 
grep '^[^0-9]' 1.txt
# 过滤任意一个或多个字符 ----- 
# . 表示任意一个字符;
# *表示零个或多个前面的字符 ;
# .*表示零个或多个任意字符,空行也包含在内 
grep 'r.o' 1.txt; grep 'r*t' 1.txt; grep 'r.*t' 1.txt 

# 指定过滤字符次数 ----- 
grep 'o\{2\}' 1.txt
# 过滤域名 ----- 
grep -o '(http://|https://)(\w+\.){2}\w+' 文件名
# 同时过滤单双引号 ----- 
grep "\<src\>" index.html |grep -o  "\<src=['|\"]([^[:space:]])*[^[:space:]]['|\"]"
# 精确匹配 ----- 
grep filename -w root
grep filename \<root\>
        文件内容如下
            root
            file1
            file2
            root2
            root3

egrep

egrep工具 是grep工具的扩展
egrep ‘o+’ 1.txt 表示1个或1个以上前面字符
egrep ‘o?’ 1.txt 表示0个或者1个前面字符
egrep ‘roo|body’ 1.txt 匹配roo或者匹配body
egrep ‘r(oo)|(at)o’ 1.txt 用括号表示一个整体
egrep ‘(oo)+’ 1.txt 表示1个或者多个 ‘oo’

. * + ? 总结

. 表示任意一个字符(包括特殊字符)
* 表示零个或多个*前面的字符
.* 表示任意个任意字符(包含空行)
+ 表示1个或多个+前面的字符
? 表示0个或1个?前面的字符
其中,+ ? grep不支持,egrep才支持。

grep -q 用于if 逻辑判断很好用。

-q 参数,本意是 Quiet; do not write anything to standard output.
Exit immediately with zero status if any match is found, even if an error was detected.
中文意思为,安静模式,不打印任何标准输出。
如果有匹配的内容则立即返回状态值0。

小应用

cat a.txt
nihao 
nihaooo
hello
# 输出 yes
if  grep -q hello a.txt ; then 
    echo yes;
else 
    echo no; 
fi 


# 输出 no
if grep -q word a.txt; then 
    echo yes; 
else 
    echo no; 
fi

三剑客之二 sed

案例

# 01. 打印指定行 ----- 
sed '10'p -n 1.txt; sed '1,4'p -n 1.txt; sed '5,$'p -n 1.txt
# 02. 打印包含某个字符串的行 ----- 
sed -n '/root/'p 1.txt 可以使用 ^ . * $等特殊符号
# 03. -e 可以实现同时进行多个任务 ----- 
sed -e '/root/p' -e '/body/p' -n 1.txt 也可以用;实现  
sed  '/root/p; /body/p' -n 1.txt
# 04. 删除行 ----- 
sed '/root/d' 1.txt;   sed '1d' 1.txt; sed '1,10d' 1.txt
# 05. 替换 ----- 
sed '1,2s/ot/to/g' 1.txt, 其中s就是替换的意思,g为全局替换,否则只替换第一次的,/也可以为 #, @ 等
# 06. 删除所有数字 ----- 
sed 's/[0-9]//g' 1.txt
# 07. 删除所有非数字 -----  
sed 's/[^0-9]//g' 1.txt
# 08. 调换两个字符串位置 ----- 
head -n2 1.txt |sed 's/\(root\)\(.*\)\(bash\)/\3\2\1/'
# 09. 直接修改文件内容 ----- 
sed -i 's/ot/to/g' 1.txt
# 10. 把文件中没一行都复制一行 ----- 
sed 's/.*/&\n&/' 文件名

# 11. 把每两行的第一行开头添加'"' 结尾添加'_R:channel",'
sed 's/.*/"&_R:channel",\n"&_W:channel",/' rw1(文件名)
文件内容如下
    Dalitek/JINGKONG/-2F DONG CHEWEI+DONG CHEDAOZHONGJIAN
    Dalitek/JINGKONG/-2F DONG CHEDAO
    Dalitek/JINGKONG/-2F BEI CHEDAO
    Dalitek/JINGKONG/-2F -3PODAO
    Dalitek/JINGKONG/-2F CHEWEIDENG NEI 1
    Dalitek/JINGKONG/-2F CHEDAODENG
    Dalitek/JINGKONG/-2F CHEWEIDENG NEI 2
    Dalitek/JINGKONG/-2F ZHONGJIAN CHEWEIDENG
    Dalitek/JINGKONG/-2F NAN PODAO DAO-3
    Dalitek/JINGKONG/-2F SHANGYE DIANTI DENGDAI

练习

把/etc/passwd 复制到/root/test.txt,用sed打印所有行
打印test.txt的3到10行
打印test.txt 中包含 'root' 的行
删除test.txt 的15行以及以后所有行
删除test.txt中包含 'bash' 的行
替换test.txt 中 'root''toor'
替换test.txt中 '/sbin/nologin''/bin/login'
删除test.txt中5到10行中所有的数字
删除test.txt 中所有特殊字符(除了数字以及大小写字母)
把test.txt中第一个单词和最后一个单词调换位置
把test.txt中出现的第一个数字和最后一个单词替换位置
把test.txt 中第一个数字移动到行末尾
在test.txt 20行到末行最前面加 'aaa:'

三剑客之二 awk

案例

# 截取文档中的某段 
awk -F ':' '{print $1}' 1.txt
# 也可以使用自定义字符连接每个段 
awk -F':' '{print $1"#"$2"#"$3"#"$4}' 1.txt
# 匹配字符或字符串 
awk '/oo/' 1.txt
# 针对某个段匹配 
awk -F ':' '$1 ~/oo/' 1.txt
# 多次匹配 
awk -F ':' '/root/ {print $1,$3}; $1 ~/test/; $3 ~/20/' 1.txt
# 条件操作符==, >,<,!=,>=;<=  
awk -F ':' '$3=="0"'  1.txt; 
awk -F ':' '$3>="500"' 1.txt; 
awk -F ':' '$7!="/sbin/nologin"'  1.txt; 
awk -F ':' '$3<$4' 1.txt ; 
awk -F ':' '$3>"5" && $3<"7"' 1.txt 
awk -F ':' '$3>"5" || $7=="/bin/bash"' 1.txt
# awk内置变量 NF(段数)  NR(行数)
head -n3 1.txt | awk -F ':' '{print NF}' 
head -n3 1.txt | awk -F ':' '{print $NF}' 
head -n3 1.txt | awk -F ':' '{print NR}' 
# 打印20行以后的行awk 'NR>20' 1.txt
awk -F ':' 'NR>20 && $1 ~ /ssh/'  1.txt 
# 更改某个段的值
awk -F ':' '$1="root"' 1.txt
# 数学计算, 把第三段和第四段值相加,并赋予第七段 
awk -F ':' '{$7=$3+$4; print $0}' 1.txt
# 计算第三段的总和 
awk -F ':' '{(tot=tot+$3)}; END {print tot}' 1.txt
# awk中也可以使用if关键词 
awk -F ':' '{if ($1=="root") print $0}' 1.txt

双引号:
    awk '{print "\""}'        #放大:awk '{print "  \"  "}'
    使用""双引号把一个双引号括起来,然后用转义字符\对双引号进行转义,输出双引号。
单引号:
    awk '{print "'\''"}'       # 放大: awk '{print  "  '  \  '  '   " }'
    使用一个双引号"",然后在双引号里面加入两个单引号'',接着在两个单引号里面加入一个转义的单引号\',输出单引号。

awk练习题


用awk 打印整个test.txt (以下操作都是用awk工具实现,针对test.txt)
查找所有包含 'bash' 的行
':' 作为分隔符,查找第三段等于0的行
':' 作为分隔符,查找第一段为 'root' 的行,并把该段的 'root' 换成 'toor' (可以连同sed一起使用)
':' 作为分隔符,打印最后一段
打印行数大于20的所有行
':' 作为分隔符,打印所有第三段小于第四段的行
':' 作为分隔符,打印第一段以及最后一段,并且中间用 '@' 连接 (例如,第一行应该是这样的形式 'root@/bin/bash'':' 作为分隔符,把整个文档的第四段相加,求和