【Shell牛客刷题系列】SHELL22 处理文本



该系列是基于牛客Shell题库,针对具体题目进行查漏补缺,学习相应的命令。

刷题链接:牛客题霸-Shell篇

该系列文章都放到专栏下,专栏链接为:《专栏:Shell》。欢迎关注专栏~

本文知识预告:

  • 本文首先复习了字符串拼接,grepsortawk命令的相关的用法;
  • 然后,给出了四种题目的解决方案,基本算是前面题目都用到过的知识点。


题目:SHELL22 处理文本

有一个文本文件nowcoder.txt,假设内容格式如下:

111:13443
222:13211
111:13643
333:12341
222:12123

现在需要编写一个shell脚本,按照以下的格式输出:

[111]
13443
13643
[222]
13211
12123
[333]
12341

相关命令学习

Shell中的字符串拼接

字符串拼接的方式很简单,直接相连即可,比如:

wz@lucky:~$ strs="1+1="
wz@lucky:~$ strs=$strs"2"
wz@lucky:~$ echo $strs
1+1=2

另外,如果有变量,可以把字符串变量添加进{},并且需要把$放到外面,直接相连就行了,如下例子:

wz@lucky:~$ name='aha'
wz@lucky:~$ strs="hello"
wz@lucky:~$ new_str=${strs}" "${name}
wz@lucky:~$ echo $new_str 
hello aha

grep:强大的文本搜索工具

grep来自于英文词组“global search regular expression and print out the line”的缩写,意思是用于全面搜索的正则表达式,并将结果输出。人们通常会将grep命令与正则表达式搭配使用,参数作为搜索过程中的补充或对输出结果的筛选,命令模式十分灵活。

与之容易混淆的是egrep命令和fgrep命令。如果把grep命令当作是标准搜索命令,那么egrep则是扩展搜索命令,等价于“grep -E”命令,支持扩展的正则表达式。而fgrep则是快速搜索命令,等价于“grep -F”命令,不支持正则表达式,直接按照字符串内容进行匹配。

语法格式: grep [参数] 文件

常用参数:

参数功能
-i忽略大小写
-c只输出匹配行的数量
-l只列出符合匹配的文件名,不列出具体的匹配行
-n列出所有的匹配行,显示行号
-h查询多文件时不显示文件名
-s不显示不存在、没有匹配文本的错误信息
-v显示不包含匹配文本的所有行
-w匹配整词
-x匹配整行
-r递归搜索
-q禁止输出任何结果,已退出状态表示搜索是否成功
-b打印匹配行距文件头部的偏移量,以字节为单位
-o-b结合使用,打印匹配的词据文件头部的偏移量,以字节为单位
-F匹配固定字符串的内容
-E支持扩展的正则表达式

awk:文本和数据进行处理的编程语言

awk命令来自于三位创始人”Alfred Aho,Peter Weinberger, Brian Kernighan “的姓氏缩写,其功能是用于对文本和数据进行处理的编程语言。使用awk命令可以让用户自定义函数或正则表达式对文本内容进行高效管理,与sedgrep并称为Linux系统中的文本三剑客。

语法格式awk 参数 文件

常用参数

参数功能
-F指定输入时用到的字段分隔符
-v自定义变量
-f从脚本中读取awk命令
-mval值设置内在限制

常用的awk内置变量

awk语法由一系列条件和动作组成,在花括号内可以有多个动作,多个动作之间用分号分隔,在多个条件和动作之间可以有若干空格,也可以没有。

变量名称说明
FILENAME当前输入文档的文件名
FNR当前输入文档的当前行号,尤其当多个输入文档时有用
FS设置字段分隔符,默认为空格或制表符
NF当前记录(行)的字段(列)个数
NR输入数据流的当前记录数(行号)
OFS输出字段分隔符,默认为空格
ORS输出记录分隔符,默认为换行符
RS输入记录分隔符,默认为换行符

awk是一种处理文本文件的编程语言,文件的每行数据都被称为记录默认以空格或制表符为分隔符每条记录被分成若干字段(列)awk每次从文件中读取一条记录

sort:对文件内容进行排序

sort命令的功能是对文件内容进行排序。有时文本中的内容顺序不正确,一行行地手动修改实在太麻烦了。此时使用sort命令就再合适不过了,它能够对文本内容进行再次排序。

语法格式:sort [参数] 文件

常用参数:

-b忽略每行前面开始出的空格字符
-c检查文件是否已经按照顺序排序
-d除字母、数字及空格字符外,忽略其他字符
-f将小写字母视为大写字母
-i除040至176之间的ASCII字符外,忽略其他字符
-m将几个排序号的文件进行合并
-M将前面3个字母依照月份的缩写进行排序
-n依照数值的大小排序
-o <输出文件>将排序后的结果存入制定的文件
-r以相反的顺序来排序
-t <分隔字符>指定排序时所用的栏位分隔字符
-k指定需要排序的栏位
-s通过禁用最后的比较来稳定排序

cut:按列提取文件内容

cut命令的功能是用于按列提取文件内容。常用的grep命令仅能对关键词进行按行提取过滤,而cut命令则是可以根据指定的关键词信息,针对特定的列内容进行过滤

语法格式:cut [参数] 文件

常用参数:

-c以字符为单位进行分割
-b以字节为单位进行分割
-d自定义分隔符,默认为制表符”TAB”
-f显示指定字段的内容
-n取消分割多字节字符
--complement补足被选择的字节、字符或字段
--out-delimiter指定输出内容是的字段分割符

参考实例

  1. 以冒号为间隔符,仅提取指定文件中第一列的内容:
lucky@DESKTOP-VQ8KID4:~$ cut -d : -f 1 /etc/passwd
root
daemon
bin
...
sshd
landscape
pollinate
lucky
  1. 仅提取指定文件中每行的前4个字符:
lucky@DESKTOP-VQ8KID4:~$ head /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

lucky@DESKTOP-VQ8KID4:~$ cut -c 1-4 /etc/passwd
root
daem
bin:
sys:
sync
...
  1. 按照指定要求分割:比如获取后缀名
lucky@DESKTOP-VQ8KID4:~$ ls | cut -d "." -f2
txt
txt
py
txt
txt
sh
md
sh
txt
py
sh

题目解决方案

方法一:awk+字符串拼接

awk -F ":" '{
  a[$1] = a[$1] $2 "\n"
}
END {for (i in a){
  	printf("[%s]\n%s",i,a[i])
  }
}' nowcoder.txt

下面的写法也可:

awk -F ":" '{
	res[$1] = (res[$1] == "" ? $2 : (res[$1] "\n" $2))
}
END {for(k in res){
    print "["k"]"
    print res[k]
  }
}' nowcoder.txt

方法二:cut+sort+grep+awk

for val in $(cat nowcoder.txt | cut -d ":" -f 1 | sort | uniq); do
	echo "[$val]"
	cat nowcoder.txt | grep $val | awk -F ":" '{print $2}'
done < nowcoder.txt

方法三:sort+awk

cat nowcoder.txt | sort -t ":" -k 1,1 -sb | awk -F ':' 'BEGIN{t=0}{if($1 != t){print "["$1"]";t=$1;print $2}else{print $2}}'

方法四:for+grep

将分号前面的先去重找出来,以此为条件,找出相应的数字即可。

number01=$(cat nowcoder.txt | awk -F':' '{print $1}' | sort | uniq -c | awk '{print $2}')
for i in $number01; do
	number02=$(grep "${i}" nowcoder.txt | awk -F':' '{print $2}')
	echo "[${i}]"
	echo -e "${number02}"
done
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奋斗的西瓜瓜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值