linux —— shell 编程(文本处理)

导读

本文为博文 linux —— shell 编程(整体框架与基础笔记)的第4小点的拓展。(本文所有语句的测试均在 Ubuntu 16.04 LTS 上进行)


1、基本文本处理

sort :用于排序,常用参数 -t 指定一行的分隔符 -k 指定具体排序的规则 -d 按字典序排列  -f 忽略大小写

    -u (unique)丢弃相同指定字段的记录

unique:报告或删除文件中重复的行。 -c 在输出行前加上出现的次数    -d  (duplicated)显示重复的行  

                  -u 仅显示不重复的行 

wc:  统计文本行数,字数和字符数。    -c 字符数    -w  单词数    -l  行数

pr:将文本转换成适合打印的格式。   -c 显示的列数(截断超出的部分)

fmt: 优化文本的格式。  -w 设置一行显示的最大行宽   -s  只对过长的行进行换行,不要自动回填。

fold:限制文本宽度(强行截断并换行)。 -w 指定宽度  -s 只在空格处换行。

cut :截取行的字段。   -delimiter  设置字段分割符 -f List 设置截取的域  

           List可以是M,M-,M-N -M;可以用逗号指定多个

join:连接两个文件的数据字段。  join file1 file2  -1 M  -2 N    M、N指定匹配的字段

tr: 文本替换。 tr set set :将str1上字符替换成str2上对于位置的字符; (可以是 tr 'a-z' 'A-Z')

        tr {-d|-s} set :-d 删除set上的每一个字符 ;-s 除去连续出现的set中的字符,至只剩下单个

        tr -c (complement 互补)使用set1的外的其他字符 [例子:tr -cs '[:lower:][:upper:]' '[\n*]' 单词表]

2、流编辑器sed

0)sed 的作用和工作方式

sed 是一个非交互式的的行编辑器,工作时,从指定的输入读入一行数据存入被称为模式空间(Pattern Space) 的临时缓冲区,然后按照指定的sed编辑命令处理缓冲区里面的内容,将结果输出到标准输出后从模式空间中删除,然后继续读取下一行继续工作。

1) 地址范围

sed -e '1,5d'  test.txt
sed -e '/^#/d' test.txt

规则表达式中使用的表达式字符:

字符 描述
^ 与行首匹配

$

与行尾匹配

.

与任意一个字符匹配
* 与之前一个字符的零个或多个出现匹配
[] 与[]之间的所有字符匹配

 2) 参数

-e     将脚本添加到命令执行,如上面的 '/^#/d'

-n    禁止模式空间的自动打印

替换文本:   sed -e "s/benson/BENSON/g"  将benson 替换成大写

      sed -e "1,10s/benson/BENSON/g" 将1-10行的benson变成大写

          s/// 的 “/”可以被替换:比如 sed -e "s:/usr/local:/usr:g" 

多条命令一起执行:  sed -n -e "=;p"   打印行号;打印行 (等价与 sed -e "=" -e "p" )

多条命令于同一地址范围:sed -n -e '1,5{s/benson/BENSON/g;s/laur/LAUR/g}'

把命令放在文件fsed里:sed -n -f fsed 

3、awk模式扫描与处理语言

awk 具有成为一门语言应有的要素:变量,函数等,是强大的处理工具。

例子:

awk -F ":" '{print "USER:" $1  "\tSHELL: " $7 }'  /etc/passwd
结果:
USER:root    SHELL: /bin/bash
USER:daemon    SHELL: /usr/sbin/nologin
USER:sync    SHELL: /bin/sync

上面的命令也可以写入文件file.awk中:

awk -f file.awk /etc/passwd
复制代码
BEGIN{ FS=":" }
{
    print "USER:" $1  "\tSHELL: " $7 
}
file.awk
复制代码
3.1 awk的变量和数组

1)用户自定义变量

命名规则:[A-Za-z_][A-Za-z0-9_]*

2) 常用的内建变量

变量 说明
FILENAME 当前输入的文件名称
FNR 当前输入的文件的记录数
FS 字段分隔符(支持正则表达式),默认空格
NF 当前记录的字段数
NR 在工作(job)中的记录数
OFS 输出字段分隔字符
ORS 输出记录分隔字符(默认为“\n”)
RS 输入记录分隔字符

3) awk数组  的字符索引支持数字、字符串

复制代码
sit[google]="https://google.com"
sit[baidu]="http;//baidu.com"

数组存储是稀疏的,可直接定义如下两项:
x[1]=1234
x[1000]=234234

delete x  将删除数组里所有的元素

删除后,可以继续定义如下:
x=567
复制代码

访问环境变量:ENVIRON["PATH"]

3.2 算数运算
awk的运算符 
运算符 描述 例子
=  +=  *=   /=  ^=  **= 赋值  
?= C条件表达式  
||   && 逻辑与或  
++-- 自增自减  
~   ~! 匹配正则表达式和不匹配正则表达式  
<   <=  >  >=  !=  == 关系运算符  
空格 连接  
+ - 加、减  
* /  % 乘除 求余  
+  -  ! 一元加减,逻辑非  
^  *** 求幂  
$ 字段引用  
in 数组成员  

awk支持的算数函数:  

    sin(x) cos(x) atan2(x,2) :x,y 范围内的余切 int(x):没有舍入地取整 exp(x)求幂 log(x):自然对数 sqrt(x) 

    rand():产生>=0 <1的随机数 srand(x):x是rand()的种子

3.3 条件和循环语句

条件语句和循环语句与C类似,支持break,continue(可以不使用;结尾)

例子:将下面记录每组一行输出

复制代码
abc,123
tttt  dddd

ddd,324
ssss  ssdd
sdfsd sdf 

dddd
sfdfsdf
待处理数据
复制代码
复制代码
BEGIN{
        FS="\n"
        RS=""    # RS设置为""将可以解析多行记录(以空行分隔)
        ORS=""      #输出记录分隔符不要换行
}
{
        x=1
        while(x<NF)
        {
                print $x "\t"
                x++
        }
        print $NF "\n"
}
使用while循环
复制代码

结果:

abc,123    tttt  dddd
ddd,324    ssss  ssdd    sdfsd sdf
dddd    sfdfsdf
处理结果
3.4 自定义函数

在函数中,指定的参数将被当做局部变量,而所有函数体内未出现在参数列表中的变量会被视为全局性。为此,awk允许声明过多的参数用于局部使用如:

function add(x,y,      sum)
{
sum = x+y
return sum
}

如果需要使用函数进行引用传递,只能通过传入数组来实现:

引用传递
3.5 字符串处理

格式化输出:

printf("%s have %d jobs","somebody",3)
strout = sprintf("%s have %d jobs","somebody",3)

格式化输出的转义字符:c s d ld (十进制长整数) u lu x lx o lo e(科学计数法表示的浮点数) f g(e或f中比较短的一种)

printf 修饰符:  - 左对齐     #显示八进制时在前面加个0;显示十六进制时在前面加0x  

         +显示defg 转换的整数时,加上正负号    0  填充空白为0

        具体的格式为:%-width.precision fotmat-specifier

awk内置字符串函数:

awk函数 描述
sub(/reg/,newsubstr,str) 替换第一个匹配的字符串
gsub(/reg/,newsubstr,str) 替换所有匹配
index(str,substr) 返回substr在str中的索引
length(str) 长度
match(str,/reg/) 如果在str中找到正则表达式/reg/匹配的串,则返回出现的位置,未找到则返回0
split(str,array,sep) 使用sep分隔到array
substr(str,position[,length]) 返回str从position开始的length个字符
tolower(str) 变小写
toupper(str) 变大写
sprintf("fmt",expr) 格式化返回字符串

 

3.6 多文件处理
10001 南京 佛挡杀佛 sdfsdf
10002 天津 发生地方  双方的发生
10003 石家庄 发生地方 发生地方
a.txt
复制代码
11000,南京
11003,天津
12000,河北省
13000,品上线
12344,石家庄
b.txt
复制代码
复制代码
BEGIN{
        FS="[ ,]"
        OFS=","
}

NR <= FNR{
        array[$2]=$1
}
NR > FNR{
        print $1,$2,array[$2]
}
join.awk
复制代码
awk  -f join.awk a.txt b.txt
复制代码
11000,南京,10001
11003,天津,10002
12000,河北省,
13000,品上线,
12344,石家庄,10003
执行结果
复制代码

 

posted @   BensonLaur  阅读(1600)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示