0%

linux脚本攻略之让文本飞

shell脚本攻略第四章之让文本飞

这一章主要是介绍一些针对文本的操作,包括grep,sed,awk,命令等。

cut的使用技巧,cut是一个将文本切分的小工具
#! /bin/bash

# cut 是一个将文本按列切分的小工具,可以指定每列的定界符,field_list 是需要显示的列,有列号醉成,用逗号隔开
cut -f field_list filename
cut -f 2,3 filename

# 读取第一列
cut -f 1 cut_data.txt

# 打印除了第三列外的其他列
cut -f 3 --complement cut_data.txt

# 执行字段的定界符
cut -f 2 -d ";" cut_data.txt
正则表达式,正则表达式的应用非常广泛,可以用于sed,grep,awk匹配文本,这里结合grep命令一起进行讲解,正则表达式的详细讲解参见正则表达式
#!/bin/bash

# 匹配文本中的所有单词
(?[a-zA-z]+?)

# 在文件中搜索一个单词 grep match_pattern filename
echo -e "this is a word next line" | grep word

# grep 也可以对多个文件进行搜索,--color 会重点标注匹配到的单词
grep "match_text" file1 file2 file3 --color=auto

# 使用正则-E 使用扩展正则表达式,-v表示invert,打印除了match_pattern外的所有行
grep -E "[a-z]+"

# 统计文本中匹配字符串的行数
grep -c "text" filename

# 打印出包含字符换的文本
grep pattern_text -n filename

# 递归搜索文件
grep "text" / -R -n

# -i 忽略大小写
echo hello world | grep -i "HELLO"

# 在目录中搜索所有的.c和.cpp文件
grep "main()" . -r --includ *.{c,cpp}

# 使用0值字节后缀的grep与xargs,-Z可以指定0值字节作为终结符
grep "test" file* -lZ | xargs -0 rm

# 打印出匹配文本之前或之后的行,之后的n行,用-A选项,之前的n行,用-B选项,之前加之后用-C选项
seq 10 | grep 5 -A 3 -B 3
grep的示例应用
#!/bin/bash

# 测试文件中是否包含特定的文本文件
function contains() {
    if [ $# -ne 2 ];
    then echo  "$0 match_text filename"
    exit -1
    fi

    match_text=$1
    filename=$2

    grep -q $match_text $filename

    if [ $? -eq 0 ];
    then echo "the text exist in the file"
    else echo "text does not exist in the file"
    fi

}

contains $1 $2
sed的使用技巧,sed是一个文本流处理工具,主要用于文本替换等操作
#!/bin/bash

# 替换指定文本中的字符串
sed 's/pattern/replace_str/' file

# -i将替换结果应用于源文件
sed -i 's/text/replace/' file

# 默认只替换第一处符合的内容,替换全部需在尾部加g
sed 's/text/replace/g' file

# 从第N出开始替换
sed 's/text/replace/ng' file


# 移除空白行,空白行用^$匹配
sed '/^$/d' file

# & 标记匹配样式的字符串,能够在替换字符串时使用已匹配的内容
echo this is a exampel | sed 's/\w\+/[&]/g'

# 子串匹配标记\1
echo this is digit 7 in a number | sed 's/digit \([0-9])/\1/'

# 引用
text=hello
echo hello world | sed "s/$text/HELLO/" 
awk命令,awk命令可以对列和行进行操作,当我们需要循环处理每一行的数据时,首先应该想到的就是awk命令
#!/bin/bash

# awk可以对列和行进行操作,他又很多内建的功能,辱数组,函数凳

# 一个awk甲苯通常由BEGIN,END和模式匹配的通用语句三部分组成
# awk 'BEGIN{print "start"} pattern {commands} END{print "end"}'

# 工作原理:先执行BEGIN语句,再从文件或stdin中读取一行,然后执行pattern,重复过程至文件读取完毕,再执行END语句

echo -e "line1\nline2" | awk 'BEGIN{print "start"} {print} END{print "END"}'

# 通常将初始化语句及打印文件头部的语句放入BEGIN语句块中,将打印结果放入END语句块中

# 特殊变量
# NR 记录数量,在执行过程中对应当前行号
# NF 字段数量,执行过程中对应当前行的字段数
# $0 变量包含了执行过程中的当前行的文本内容
# $1 包含了第一个字段的文本内容
# $2 包含了第二个字段的文本内容

echo -e "line1 f2 f3\nlin3 f4 f5\nline3 f6 f7" | \
awk '{print "line no :" NR ",No of fields:" NF , "$0="$0}'

# 传递外部变量到awk
var1="aa" var2="bb"
echo | awk '{print v1,v2}' v1=$var1 v2=$var2

# 设置定界符
awk -F: '{print $NF }' /etc/password

# 从awk中读取命令输出,getline将grep的输出读入cmdout,再打印出来
echo | awk '{ "grep root /etc/passwd" | getline cmdout ; print cmdout}'

# 在awk中使用循环
for(i in array){print array[i] ; }
统计文件词频的工具方法,这个方法综合应用了grep,及awk命令,可以巩固上面所学,具体落地到实际的应用当中去
#!/usr/bin/env bash

# 使用数组统计词频
# 判断参数是否是一个
if [[ $# -ne 1 ]];
then echo "Usage: $0 filename";
exit -1
fi

filename=$1
# 输出是单词的文本,-o选项打印出由换行符分割的匹配字符序列
egrep -o  "\b[[:alpha:]]+\b" ${filename} | \
awk '{ count[$0]++ }
END { printf ("%-14s%s\n" , "word","count");
for (ind in count)
{
    printf ("%-14s%d\n", ind, count[ind]); }
}'
paste命令,这是一个对列进行拼接的工具
#1/bin/bash

# 按列拼接
paste paste1.txt paste2.txt
~~