前言
本栏目主要是科普shell的一些基本使用,但题目比较少,做的不够过瘾(官方只有四道题)
专栏地址:leetcode:shell题目
但是这四道题的一些基本命令都比较常用,在笔试中的选择题遇到的概率比较高(因为下面的命令真的很有用=-=)推荐你看看
192. 统计词频(中等)
题目:
写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率。
为了简单起见,你可以假设:
- words.txt只包括小写字母和 ’ ’ 。
- 每个单词只由小写字母组成。
- 单词间由一个或多个空格字符分隔。
示例:
假设 words.txt 内容如下:
the day is sunny the the
the sunny is is
你的脚本应当输出(以词频降序排列):
the 4
is 3
sunny 2
day 1
说明:
不要担心词频相同的单词的排序问题,每个单词出现的频率都是唯一的。
你可以使用一行 Unix pipes 实现吗?
思路:
#tr 删除指定字符,-s为连续重复删除
#uniq删除重复出现的行 ,-c统计重复出现的次数
#sort 排序,-r主要是为了反转顺序,-n次数大于10的时候,代表按照数字排序,而不是ascii排序
#awk 输出打印,配合print函数,将其第一列和第二列互换
cat words.txt|tr -s ' ' '\n'|sort|uniq -c|sort -nr|awk '{print$2,$1}'
以下为注释:
- cat 显示文本文件
- tr 转换或删除文件中字符,配合-s参数缩减连续重复的指定单个字符
the
day
is
sunny
the
the
the
sunny
is
is
- sort将其上面的排序
- uniq检查以及删除重复出现的相邻行列,配合参数-c使用(每一列旁边显示重复出现的次数)
- sort再次将其排序,主要是配合参数-r 相反顺序,为了让其最大的在第一个输出
- awk 以及print 打印函数 将其第一列和第二列互换
除了以上的代码格式 还有另外一种替换方式:
xargs -n1
,其作用为将所有航转换为当列显示
cat words.txt|xargs -n1|sort|uniq -c|sort -nr|awk '{print$2,$1}'
193. 有效电话号码(简单)
题目:
给定一个包含电话号码列表(一行一个电话号码)的文本文件 file.txt,写一个单行 bash 脚本输出所有有效的电话号码。
你可以假设一个有效的电话号码必须满足以下两种格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)
你也可以假设每行前后没有多余的空格字符。
示例:
假设 file.txt 内容如下:
987-123-4567
123 456 7890
(123) 456-7890
你的脚本应当输出下列有效的电话号码:
987-123-4567
(123) 456-7890
思路:
关于正则的一些注意事项:
^ 要求匹配的字符串是在行首
$ 要求匹配的字符串在行尾
{3} 前面的连续匹配三个数字
这道题的思路主要是正则表达式的配对
- (xxx) xxx-xxxx 表示为
^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$
- xxx-xxx-xxxx 表示为
^[0-9]{3}-[0-9]{3}-[0-9]{4}$
取两者 前面不一样的部分座位 并集,后面 公共部分 作为交集
# (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)
# 加入-p的参数主要是为了配合使用perl的正则表达式用法
grep -P '^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$' file.txt
也可使用awk打印输出,但是awk命令的正则表达式要放在"//“中间,所以首尾都有一个”/"
awk '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$/' file.txt
194. 转置文件(中等)*
题目:
给定一个文件 file.txt,转置它的内容。
你可以假设每行列数相同,并且每个字段由 ’ ’ 分隔。
示例:
假设 file.txt 文件内容如下:
name age
alice 21
ryan 30
应当输出:
name alice ryan
age 21 30
思路:
类似编程模式,获取其列的个数,遍历列,输出行的内容
- 具体获取列的个数:通过
head -n 1
表示获取指定行的内容,此处获取第一行的内容
wc 获取个数,通过-w(word)参数获取其单词的个数 - 遍历列的代码格式:
for i in $(seq 1 $columns)
- 循环输出每一列的内容,通过do,done
- 输出的格式通过awk+print(shell对单引号和双引号,按从左到右的顺序成对匹配
awk命令用单引号引起来,就是防止shell对其中内容进行解释)
所以其命令为awk '{print $' "$i" '}' file.txt
拆分出来就是awk '{print $'
以及"$i"
以及'}'
,只有对其"$i"
进行了解释,其他都没有动 - 通过xrag对其每一个按行显示
详情参考文档如下:
awk引用外部变量
⭐️ LeetCode解题系列 ⭐️ 194. 转置文件(Shell)题解
# 显示文本中的内容,head -n 1表示读取第一行,wc表示获取多少个频数,-w表示获取其当前行中的列有多少个
columns=$(cat file.txt | head -n 1 | wc -w)
for i in $(seq 1 $columns)
do
awk '{print $' "$i" '}' file.txt | xargs
done
195. 第十行(简单)
题目:
给定一个文本文件 file.txt,请只打印这个文件中的第十行。
示例:
假设 file.txt 有如下内容:
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10
你的脚本应当显示第十行:
Line 10
说明:
- 如果文件少于十行,你应当输出什么?
- 至少有三种不同的解法,请尝试尽可能多的方法来解题。
思路:
tail -n +10
表示从第10行开始,文件如果不足十行不会输出tail -n 10
表示现显示最后的十行
显示第10行开始的那一行
tail -n +10 file.txt|head -1
或者执行set -p(在当前输出到\n结束)
sed -n 10p file.txt
# 打印1到10行,则应该这么输出
set -n '1,10p' file.txt
或者使用awk直接打印输出
awk 'NR==10' file.txt