【Shell牛客刷题系列】SHELL9 统计每个单词出现的个数:一起学习sort排序命令和uniq去重命令

2023-11-08



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

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

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

本文知识预告:

  • 首先学习了对文件内容进行排序的sort命令和去除文件中重复内容的uniq命令;
  • 然后结合相关知识给出了三种题目的解决方案。


题目:SHELL9 统计每个单词出现的个数

写一个bash脚本以统计一个文本文件nowcoder.txt 中每个单词出现的个数。

为了简单起见,你可以假设:nowcoder.txt只包括小写字母和空格,每个单词只由小写字母组成,单词间由一个或多个空格字符分隔。

假设 nowcoder.txt 内容如下:

welcome nowcoder
welcome to nowcoder
nowcoder

说明:不要担心个数相同的单词的排序问题,每个单词出现的个数都是唯一的。

相关命令学习

sort:对文件内容进行排序

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

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

常用参数:

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

参考实例

  1. 对指定的文件内容按照字母顺序进行排序:
lucky@DESKTOP-VQ8KID4:~$ cat fruits.txt
watermelon
apple
blackberry
fig
kiwi
lemon
grapefruit
pineapple
banana
orange
lucky@DESKTOP-VQ8KID4:~$ sort fruits.txt
apple
banana
blackberry
fig
grapefruit
kiwi
lemon
orange
pineapple
watermelon
  1. 对指定的文件内容按照数字大小进行排序:
lucky@DESKTOP-VQ8KID4:~$ cat num.txt
32
2
56
321
33
22
1
45
lucky@DESKTOP-VQ8KID4:~$ sort -n num.txt
1
2
22
32
33
45
56
321
  1. 以冒号:为间隔符,对指定的文件内容按照数字大小对第3列进行排序:
lucky@DESKTOP-VQ8KID4:~$ cat /etc/passwd | sort -t : -k 3 -n
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
...
lucky:x:1000:1000:,,,:/home/lucky:/bin/bash
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin

uniq:去除文件中的重复内容行

uniq命令来自于英文单词unique的缩写,中文译为独特的、唯一的,其功能是用于去除文件中的重复内容行uniq命令能够去除掉文件中相邻的重复内容行,如果两端相同内容中间夹杂了其他文本行,则需要先使用sort命令进行排序后再去重复,这样保留下来的内容就都是唯一的了。

划重点:去除相邻重复内容行!

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

常用参数:

-c 打印每行在文本中重复出现的次数
-d 每个重复纪录只出现一次
-u 只显示没有重复的纪录

参考实例

  1. 对指定的文件进行去重操作:
lucky@DESKTOP-VQ8KID4:~$ cat test.txt
nowcoder
nowcoder
nowcoder
to
welcome
welcome
lucky@DESKTOP-VQ8KID4:~$ uniq test.txt
nowcoder
to
welcome
  1. 统计相同内容行在文件中重复出现的次数:
lucky@DESKTOP-VQ8KID4:~$ uniq -c test.txt
      3 nowcoder
      1 to
      2 welcome
  1. 仅显示指定文件中存在一模一样内容行的信息:
lucky@DESKTOP-VQ8KID4:~$ uniq -d test.txt
nowcoder
welcome
  1. 仅显示指定文件中没有存在一摸一样内容行的信息:
lucky@DESKTOP-VQ8KID4:~$ uniq -u test.txt
to

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

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

语法格式awk 参数 文件

常用参数

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

常用的awk内置变量

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

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

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

例子:

  1. 仅显示指定文件中第1、2列的内容(默认以空格为间隔符):
lucky@DESKTOP-VQ8KID4:~/shell$ awk '{print $1,$2}' nowcoder.txt
#include <iostream>
using namespace
int main()
{
int a
int b
cout <<
return 0;
}
  1. 以冒号为间隔符,仅显示指定文件中第1列的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ awk -F : '{print $1,$2}' /etc/passwd
root x
daemon x
bin x
...
tcpdump x
sshd x
landscape x
pollinate x
lucky x

/etc/passwd文件中的内容由:分隔开。

  1. 以冒号为间隔符,显示系统中所有UID号码大于500的用户信息(第3列):
lucky@DESKTOP-VQ8KID4:~/shell$ awk -F : '$3>=500' /etc/passwd
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
lucky:x:1000:1000:,,,:/home/lucky:/bin/bash
  1. 仅显示指定文件中含有指定关键词main的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ awk '/main/{print}' nowcoder.txt
int main()
  1. 以冒号为间隔符,仅显示指定文件中最后一个字段的内容:
lucky@DESKTOP-VQ8KID4:~/shell$ awk -F : '{print $NF}' /etc/passwd
/bin/bash
/usr/sbin/nologin
/usr/sbin/nologin
...
/usr/sbin/nologin
/bin/false
/bin/bash
  1. 输出行号,NR将所有文件的数据视为一个数据流,而FNR则是将多个文件的数据视为独立的若干个数据流,遇到新文件时行号从1开始重新递增。
lucky@DESKTOP-VQ8KID4:~$ awk '{print NR}' first.txt three.sh
1
2
3
lucky@DESKTOP-VQ8KID4:~$ awk '{print FNR}' first.txt three.sh
1
1
2

tr:字符转换工具

tr命令来自于英文单词transform的缩写,中文译为转换,其功能是用于字符转换。tr命令是一款批量字符转换、压缩、删除的文本工具,但仅能从标准输入中读取文本内容需要与管道符或输入重定向操作符搭配使用

语法格式:tr [参数] 字符串1 字符串2

常用参数:

-c 反选字符串1的补集(取反)
-d 删除字符串1中出现的所有字符
-s 删除所有重复出现的字符序列

将指定文件中的小写字母转换成大写字母后输出内容到终端界面:

lucky@DESKTOP-VQ8KID4:~$ tr [a-z] [A-Z] < hello.py
ABC
567
AAA
BBB
CCC

删除指定文件中所有的数字后输出内容到终端界面:

lucky@DESKTOP-VQ8KID4:~$ tr -d [0-9] < hello.py
abc

aaa
bbb
ccc

将指定文件中的多个相邻空行去重后输出内容到终端界面:

lucky@DESKTOP-VQ8KID4:~$ tr -s "[\n]" < nowcoder.txt
abc
567
aaa
bbb
ccc

xargs:给其他命令传参数的过滤器

xargs命令来自于英文词组” extended arguments“的缩写,其功能是用于给其他命令传参数的过滤器xargs命令能够处理从标准输入管道符输入的数据,并将其转换成命令参数,也可以将单行或多行输入的文本转换成其他格式

xargs命令默认接收的信息中,空格是默认定界符,所以可以接收包含换行和空白的内容

语法格式: xargs [参数]

常用参数:

-n 多行输出
-d 自定义一个定界符
-I 指定一个替换字符串{}
-t 打印出xargs执行的命令
-p 执行每一个命令时弹出确认

参考实例

  1. 默认以空格为定界符,以多行形式输出文件内容,每行显示一三段内容值:
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt | xargs -n 1
how
they
are
implemented
and
applied
in
computer
  1. 指定字符X为定界符,默认以单行的形式输出字符串内容:
lucky@DESKTOP-VQ8KID4:~$ echo "FirstXSecondXThirdXFourthXFifth" | xargs -dX
First Second Third Fourth Fifth

  1. 定字符X为定界符,以多行形式输出文本内容,每行显示两段内容值:
lucky@DESKTOP-VQ8KID4:~$ echo "FirstXSecondXThirdXFourthXFifth" | xargs -dX -n 2
First Second
Third Fourth
Fifth

  1. 设定每一次输出信息时,都需要用户手动确认后再显示到终端界面:
lucky@DESKTOP-VQ8KID4:~$ echo "FirstXSecondXThirdXFourthXFifth" | xargs -dX -n 2 -p
echo First Second ?...y
First Second
echo Third Fourth ?...y
Third Fourth
echo 'Fifth'$'\n' ?...n

题目解决方案

方法一:xargs+sort+uniq+awk统计频率

lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt | xargs -n 1 | sort | uniq -c | sort -n
| awk '{print $2, $1}'
to 1
welcome 2
nowcoder 3

下面拆分一下步骤:

  1. cat查看内容
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt
welcome nowcoder
welcome to nowcoder
nowcoder
  1. xargs转为单行输出
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt  | xargs -n 1
welcome
nowcoder
welcome
to
nowcoder
nowcoder
  1. sort将结果按照字符大小排序
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt  | xargs -n 1 | sort
nowcoder
nowcoder
nowcoder
to
welcome
welcome
  1. uniq统计重复行
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt  | xargs -n 1 | sort | uniq -c
      3 nowcoder
      1 to
      2 welcome
  1. sort对第1列统计结果排序
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt  | xargs -n 1 | sort | uniq -c | sort
      1 to
      2 welcome
      3 nowcoder
  1. awk换行输出
lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt  | xargs -n 1 | sort | uniq -c | sort | awk '{print $2,$1}'
to 1
welcome 2
nowcoder 3

方法二:tr+sort+uniq+awk统计频率

tr -s "空格"替换为“换行”可以将所有单词列成1列

lucky@DESKTOP-VQ8KID4:~$ cat nowcoder.txt | tr -s ' ' '\n' | sort | uniq -c | sor
t | awk '{print $2, $1}'
to 1
welcome 2
nowcoder 3

方法三:awk命令搭配for循环

lucky@DESKTOP-VQ8KID4:~$ awk '{for(i=1;i<=NF;i++) a[$i]+=1}END{for(x in a) print x,a[x]}' nowcoder.txt | sort -k 2
to 1
welcome 2
nowcoder 3
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Shell牛客刷题系列】SHELL9 统计每个单词出现的个数:一起学习sort排序命令和uniq去重命令 的相关文章

  • 如何在 Windows 下向 .sh 脚本传递参数?

    我正在尝试在 Windows 下执行 sh 脚本 我安装了 Git 它允许我执行 sh 文件 但是 如果不使用 sh 作为执行前缀 我似乎无法传递任何参数 我的 sh 文件 echo Test 1 如果我用以下命令执行它 gt sh tes
  • CentOS:无法安装 Chromium 浏览器

    我正在尝试在 centOS 6 i 中安装 chromium 以 root 用户身份运行以下命令 cd etc yum repos d wget http repos fedorapeople org repos spot chromium
  • NPTL 和 POSIX 线程有什么区别?

    NPTL 和 POSIX 线程之间的基本区别是什么 这两者是如何演变的 POSIX 线程 pthread 不是一个实现 它是几个函数的 API 规范 纸上的标准 英文 其名称以pthread 以及定义在
  • Linux:如何从特定端口发送TCP数据包?

    如何打开原始套接字以从特定 TCP 端口发送 我希望所有连接始终来自临时端口以下的一系列端口 如果您正在使用raw套接字 然后只需在数据包标头中填写正确的 TCP 源端口即可 相反 如果您使用 TCP 套接字接口 socket connec
  • 从 shell 命令调用 SOAP 请求

    我使用curl 向Web 服务发送SOAP 请求 并使用shell 脚本获取响应 请在下面找到我正在使用的命令 curl H Content Type text xml charset utf 8 H SOAPAction d sample
  • 在 bash 脚本中提取 XML 值 [重复]

    这个问题在这里已经有答案了 我正在尝试从 xml 文档中提取一个值 该文档已作为变量读入我的脚本中 原始变量 data is
  • 从 UNIX 命令行向串行端口发送字节?

    我想使用命令行将字节流发送到串行端口 这可能吗 我的串口位于 dev cu usbserial A700dYoR在我的 Mac 上 例如 如果我想将整数 50 或字符串 data 发送到该串行端口 我该怎么做 我对 UNIX 的了解非常有限
  • PHP 无法打开流:是一个目录

    非常简单的 PHP 脚本 我在我亲自设置的 Ubuntu Web 服务器上的 EE 模板中运行 我知道这与权限有关 并且我已经将我尝试写入的目录的所有者更改为 Apache 用户 我得到的错误是 遇到 PHP 错误 严重性 警告 消息 fi
  • 如何从我自己的脚本向 Fish shell 提供制表符补全?

    我运行的是 Ubuntu 13 10 和 Fish 2 1 0 我想自己编写一个 Python 脚本来从命令行执行一些任务 该脚本将需要命令行参数 我怎样才能编写我的脚本 以便 Fish 可以请求并获取给定参数的可能值 潜在值列表是动态的
  • ftrace:仅打印trace_printk()的输出

    是否可以只转储trace printk 输出于trace文件 我的意思是过滤掉函数跟踪器 或任何其他跟踪器 中的所有函数 一般来说 您可以在选项目录中关闭选项 sys kernel debug tracing options Use ls显
  • 查找哪个程序运行另一个程序

    我有一个 NAS 运行在 Redhat Linux 的有限版本上 我按照指示破解了它 这样我就可以访问 shell 这很有帮助 我还做了一些修改 其他人也做过修改 除了一个问题之外 它们似乎都工作得很好 不知何故 每隔 22 天 系统就会关
  • 如何通过ssh检查ubuntu服务器上是否存在php和apache

    如何通过ssh检查Ubuntu服务器上apache是 否安装了php和mysql 另外如果安装的话在哪个目录 如果安装了其他软件包 例如 lighttpd 那么它在哪里 确定程序是否已安装的另一种方法是使用which命令 它将显示您正在搜索
  • shell-out 值到 md5(加密)函数

    我正在寻找一种解决方案 我正在构建 JSON 记录 并需要在 JQ 中生成一些文本 但将此文本通过管道传输到 MD5 求和函数并将其用作键的值 echo first John last Big jq id first last md5 通过
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • MySQL 中的创建/写入权限

    我的设备遇到一些权限问题SELECT INTO OUTFILE陈述 当我登录数据库并执行简单的导出命令时 例如 mysql gt select from XYZ into outfile home mropa Photos Desktop
  • 在两次之间每分钟执行一次 Cronjob

    我需要在 crontab 中每分钟运行一个 bash 脚本8 45am and 9 50am每天的 Code 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 8 home pull sh gt ho
  • 进程退出后 POSIX 名称信号量不会释放

    我正在尝试使用 POSIX 命名信号量进行跨进程同步 我注意到进程死亡或退出后 信号量仍然被系统打开 在进程 打开它 死亡或退出后是否有办法使其关闭 释放 早期的讨论在这里 当将信号量递减至零的进程崩溃时 如何恢复信号量 https sta
  • 监视目录的更改

    很像一个类似的问题 https stackoverflow com questions 112276 directory modification monitoring 我正在尝试监视 Linux 机器上的目录以添加新文件 并希望在这些新文
  • 如果在等待“read -s”时中断,在子进程中运行 bash 会破坏 tty 的标准输出吗?

    正如 Bakuriu 在评论中指出的那样 这基本上与BASH 输入期间按 Ctrl C 会中断当前终端 https stackoverflow com questions 31808863 bash ctrlc during input b
  • 快速像素绘图库

    我的应用程序以每像素的方式生成 动画 因此我需要有效地绘制它们 我尝试过不同的策略 库 但结果并不令人满意 尤其是在更高分辨率的情况下 这是我尝试过的 SDL 好的 但是慢 OpenGL 像素操作效率低下 xlib 更好 但仍然太慢 svg

随机推荐