shell练习题,记录一下leecode上四道shell题

记录一下leecode上四道shell题
1、打印第十行

给定一个文本文件 file.txt,请只打印这个文件中的第十行。

假设 file.txt 有如下内容:

Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
Line 9
Line 10

说明:
\1. 如果文件少于十行,你应当输出什么?
\2. 至少有三种不同的解法,请尝试尽可能多的方法来解题。

思路:判断文件行数,超过十行则打印第十行,不足十行则输出一个固定值(如”文本不足十行”或null)

统计行数的几种方法

root@mkp:/dbfile/xby#  cat file.txt | wc -l
10
root@mkp:/dbfile/xby# sed -n "$=" file.txt
10
root@mkp:/dbfile/xby# grep -c "" file.txt
10
root@mkp:/dbfile/xby# awk 'END{print NR}' file.txt
10
root@mkp:/dbfile/xby# awk '{print NR}' file.txt |tail -n1
10

打印输出第十行

root@mkp:/dbfile/xby# awk 'NR == 10' file.txt #NR在awk中指行号
Line 10
root@mkp:/dbfile/xby# sed -n 10p file.txt #-n表示只输出匹配行,p表示Print
Line 10
root@mkp:/dbfile/xby# tail -n+10 file.txt |head -1  #tail -n +10表示从第10行开始输出
Line 10

代码及执行结果

row_num=$(cat file.txt | wc -l)
echo $row_num
if [ $row_num -lt 10 ];then
    echo "The number of row is less than 10"
else
    awk 'NR == 10' file.txt
fi

root@mkp:/dbfile/xby# sh line_count.sh
10
Line 10
2、转置文件

给定一个文件 file.txt,转置它的内容。

你可以假设每行列数相同,并且每个字段由 ' ' 分隔。

示例:

假设 file.txt 文件内容如下:

name age
alice 21
ryan 30

应当输出:

name alice ryan
age 21 30

**思路:**xargs多行变单行,统计好行数,用awk +print循环打印;

awk + print打印列,获取指定列的数据

root@mkp:/dbfile/xby# cat file.txt 
name age
alice 21
ryan 30
root@mkp:/dbfile/xby# awk '{print $1}' file.txt 
name
alice
ryan
root@mkp:/dbfile/xby# awk '{print $2}' file.txt 
age
21
30

xargs多行变单行

xargs 这个命令,可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。

root@mkp:/dbfile/xby# awk '{print $1}' file.txt 
name
alice
ryan
root@mkp:/dbfile/xby# awk '{print $1}' file.txt |xargs
name alice ryan

如果有多列的情况下,输出只能按次序只能变成单行。也就是如下

root@mkp:/dbfile/xby# cat file.txt 
name age
alice 21
ryan 30
root@mkp:/dbfile/xby# cat file.txt |xargs
name age alice 21 ryan 30

head + wc 获取列数
通过 head -n 命令可以获取文件指定行数的内容,再使用 wc -w 即可获取当前行的所有列数。由于本题每行列数相同,因此我们取第一行即可

root@mkp:/dbfile/xby# cat file.txt |head -1 |wc -w
2

最终代码,用循环输出

# 获取第一行,然后用wc来获取列数
COLS=`head -1 file.txt | wc -w`
# 使用awk依次去输出文件的每一列的参数,然后用xargs做转置
for (( i = 1; i <= $COLS; i++ )); do
    # 这里col就是在代码里要替换的参数,而它等于$i
    awk -v col=$i '{print $col}' file.txt | xargs
done
3、有效电话号码

给定一个包含电话号码列表(一行一个电话号码)的文本文件 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

思路:
题目的核心是匹配符合规则的字符串,因为规则比较单一,所以使用正则表达式来检索符合要求的字符串即可。

使用正则表达式描述规律
正则表达式的重点有三:特殊字符、限定字符、定位符
熟练掌握这三点,大部分的正则表达都不在话下~

特殊字符:勿忘加上转义符’’
限定字符:限定字符出现的次数,掌握它也就get了精华,麻麻再也不用担心我读不懂漂亮的表达式了。
定位符:稍加理解,就能get到的好技巧

表达 xxx-xxx-xxxx

^[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$

使用限定符来限定数字出现的次数,优化为如下表达

^[0-9]{3}-[0-9]{3}-[0-9]{4}$

同时表示xxx-xxx-xxxx和 (xxx) xxx-xxxx

使用特殊字符()和|。用()来标记一个表达式,使用|来指明两项之间的任意选择。

^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$

grep与awk

grep -P '^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$' file.txt
awk '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$/' file.txt
gawk '/^([0-9]{3}-|\([0-9]{3}\) )[0-9]{3}-[0-9]{4}$/' file.txt
4、统计词频

写一个 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

题解

root@mkp:/dbfile/xby# cat words.txt | tr -s ' ' '\n' | sort | uniq -c | sort -nr | awk '{ print $2, $1 }'
the 4
is 3
sunny 2
day 1

解题步骤

切割

tr 命令用于转换或删除文件中的字符
-s:缩减连续重复的字符成指定的单个字符

cat Words.txt| tr -s ' ' '\n'

排序单词

cat Words.txt| tr -s ' ' '\n' | sort

统计单词出现次数

uniq 命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用。
-c:在每列旁边显示该行重复出现的次数。

cat Words.txt| tr -s ' ' '\n' | sort | uniq -c

排序单词出现次数

-r:以相反的顺序来排序

-n: 按数字排序(当单词的出现次数大于10时,sort 需要考虑按数字排序,而非默认的按 ascii 码排序)

cat Words.txt| tr -s ' ' '\n' | sort | uniq -c | sort -nr

打印

cat Words.txt| tr -s ' ' '\n' | sort | uniq -c | sort -nr | awk '{print $2, $1}'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值