shell编程

shell 编程实例

需求:写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率。
为了简单起见,你可以假设:
words.txt只包括小写字母和 ' ' 。
每个单词只由小写字母组成。
单词间由一个或多个空格字符分隔。
来源:力扣(LeetCode)

题目链接:https://leetcode-cn.com/problems/word-frequency
脚本代码:

awk '{for(i=1;i<=NF;i++){asso_array[$i]++;}};END{for(w in asso_array){print w,asso_array[w];}}' world.txt

简单解释:
awk是一种编程语言,主要用于在linux/unix下对文本和数据进行处理,是linux/unix下的一个工具。数据可以来自标准输入、一个或多个文件,或其它命令的输出。
awk的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。
基本格式为:

awk 选项 '命令部分' 文件名
特别说明:
引用shell变量需用双引号引起

想了解更多关于awk的请点击这里
首先明确awk是按行处理,即每次处理一行数据,处理完后继续处理下一行数据。
这里选项部分默认为空格为分隔符。
命令部分格式为 'BEGIN{awk语句};{处理中};END{awk语句}'
①BEGIN:表示在程序开始前执行。

②END :表示所有文件处理完后执行。

③用法:‘BEGIN{开始处理之前};{处理中};END{处理结束后}’。

这里还用涉及到shell编程中关联数组的概念,关联数组我们可以简单的当成一个字典来看。(关联数组在这里爱点不点吧!)
{for(i=1;i<=NF;i++){asso_array[$i]++;}},这行命令表示从某一行的第一列开始处理,(NF表示每一行的列数),以分割的每一个字符串为下标(索引),存储的是字符串出现的次数,用一个循环遍历所有行,得到一个以字符串为下标,字符串出现的次数为值得关联数组,处理结束后输出内容即可。

需求2:给定一个包含电话号码列表(一行一个电话号码)的文本文件 file.txt,  
写一个 bash 脚本输出所有有效的电话号码。你可以假设一个有效的电话号码必须  
满足以下两种格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)

来源:力扣(LeetCode)
链接:题目链接
测试文件grep.txt里写入以下内容
在这里插入图片描述用正则表达式进行筛选:
grep -P ‘^([0-9]{3}-|([0-9]{3}) )[0-9]{3}-[0-9]{4}$’ file.txt
解析:此问题采用grep+正则表达式来解决

grep -P '^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$'  grep.txt

在这里插入图片描述
解析:grep支持正则表达式,但是只支持一般得正则表达式,-P表示采用扩展的正则表达式,
这里要区分一下(),[],{},这三个是正则表达式中的特殊字符,要想表示原来的字符得用’\'进行转义。
() 是为了提取匹配字符串的,表达式中有几个()就有几个相应的匹配字符串
(\s*)表示连续空格的字符串
[] 是定义匹配的字符范围。比如[a-zA-Z0-9]表示相应位置的字符要匹配英文字符和数字。[\s表示空格或者号]
{}一般是用来匹配的长度。比如\s{3}表示匹配三个空格,\s[1,3]表示匹配1到3个空格
(0-9)匹配’0-9’本身。[0-9]匹配数字(注意后面有,可以为空)[0-9]+匹配数字(注意后面有+,不可以为空),
{0-9}写法是错误的
[0-9]{0,9}表示长度为0到9的数字字符串。
题目解析地址

题目三:
题目来源:https://leetcode-cn.com/problems/transpose-file/
要求:给定一个文件 file.txt,转置它的内容。
你可以假设每行列数相同,并且每个字段由 ’ ’ 分隔.
示例:
假设 file.txt 文件内容如下:

name age
alice 21
ryan 30

应当输出:

name alice ryan
age 21 30

解析来源:https://leetcode-cn.com/problems/transpose-file/solution/awkming-ling-yong-shu-zu-chu-cun-dai-shu-chu-jie-g/
awk是一行一行地处理文本文件,运行流程是:

先运行BEGIN后的{Action},相当于表头
再运行{Action}中的文件处理主体命令
最后运行END后的{Action}中的命令

有几个经常用到的awk常量:NF是当前行的field字段数;NR是正在处理的当前行数。

注意到是转置,假如原始文本有m行n列(字段),那么转置后的文本应该有n行m列,即原始文本的每个字段都对应新文本的一行。我们可以用数组res来储存新文本,将新文本的每一行存为数组res的一个元素。

在END之前我们遍历file.txt的每一行,并做一个判断:在第一行时,每碰到一个字段就将其按顺序放在res数组中;从第二行开始起,每碰到一个字段就将其追加到对应元素的末尾(中间添加一个空格)。

文本处理完了,最后需要输出。在END后遍历数组,输出每一行。注意printf不会自动换行,而print会自动换行。

awk '{
	for (i=1;i<=NF;i++)
	{
   		 if (NR==1){
         res[i]=$i
    }
    else
    {
        res[i]=res[i]" "$i
    }
}
}END{
	for(j=1;j<=NF;j++){
    print res[j]
    }
}' file.txt

作者:gao-si-huang-bu
链接:https://leetcode-cn.com/problems/transpose-file/solution/awkming-ling-yong-shu-zu-chu-cun-dai-shu-chu-jie-g/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值