【shell 练习】菜鸡的自我修养~

前言

工作中经常有需要写一个简单shell脚本的情景,每次都要花费一些时间来用啥学啥,加起来用掉很多时间,所以打算用shell刷一些题,来锻炼自己的shell能力~


1. 词频统计

题目描述

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

做法

1. map

当成一个题目来看的话,最先想到就直接map就结束了,搜索后学习了一波map的用法,但是这里map不会按照value把key排序,所以加了个桶排,实现起来很蠢,对,我很蠢~

#!/bin/bash
declare -A map
declare -A rmap
words=$(cat ./words.txt)
for i in $words
do
    map[$i]=$((${map[$i]}+1))
done
for i in ${!map[@]}
do
    rmap[${map[$i]}]=$i
done
for i in $(seq 10000 -1 1)
do
    if [ "${rmap[$i]}" != "" ];
    then
        echo ${rmap[$i]} $i
    fi
done

2. tr + sort + uniq + awk

首先用tr命令去掉文本中多余的空格和换行符,之后对整个文本sort,用uniq -c 来去重并展示出现次数。
之后再按照数值sort一次用awk换列输出即可。

cat words.txt | tr -s ' ' '\n' | sort  | uniq -c | sort -r | awk '{print $2 " " $1}'

知识点

0.基本操作

1. for 循环 1 - 10 
for i in $(seq 1 10) 
do
	echo $i
done
2. for 循环 10 - 1
其实增序for循环时隐藏了一个变量 1 ,所以降序时加上-1即可。
for i in $(seq 10 -1 1)
3. if 语句
if [ command ]; then
	#符合该条件执行的语句
elif [ command ]; then
	#符合该条件执行的语句
else 
	#符合该条件执行的语句
fi 
4. 字符串判等
[ "$a" == "$b" ]
5. 字符串判空
[ "$a" == "" ]

1.declare

declare 用来给变量 声明/取消声明 某个属性。

declare [+/-][选项] 变量名
选项:
   -:给变量舍得类型属性
   +:取消变量的类型属性
  -a:将变量声明为数组型
  -a:  将变量声明为map型
  -i:将变量声明为整型
  -x:将变量声明为环境变量
  -r:将变量声明为只读变量
  -p:查看变量的被声明的类型

2. map

1. 声明变量a为 map
declare -A a
2. 遍历整个map
for i in ${!map[@]}
do
   echo $i
done
3. 使用map的value值
${map[$key]}

3.tr

tr的用途

Linux tr 命令用于转换或删除文件中的字符。
tr 指令从标准输入设备读取数据,经过字符串转译后,将结果输出到标准输出设备。

tr的语法

tr [OPTION]…SET1[SET2]

-c, --complement:反选设定字符。也就是符合 SET1 的部份不做处理,不符合的剩余部份才进行转换
-d, --delete:删除指令字符
-s, --squeeze-repeats:缩减连续重复的字符成指定的单个字符
-t, --truncate-set1:削减 SET1 指定范围,使之与 SET2 设定长度相等
–help:显示程序用法信息
–version:显示程序本身的版本信息

用法示例

1. 将a.txt中所有的a替换成b
cat a.txt | tr 'a' 'b'
2. 将a.txt中所有的a替换成b,c替换成d
cat a.txt | tr 'ab' 'cd'
3. 将a.txt中所有小写字母替换成对应的大写字母
cat a.txt | tr a-z A-Z
4. 合并 a.txt中所有连续的空格及换行
cat a.txt | tr -s ' ' '\n'
5. -t的使用,使SET1长度和SET2相等,例如下面的效果是把a.txt中所有a替换成b.
因为SET1的长度被限制为与SET2相等。
cat a.txt | tr -t 'ac' 'b'

4.sort

sort 语法

用法:sort [选项]… [文件]…
串联排序所有指定文件并将结果写到标准输出。

排序选项:

-b, --ignore-leading-blanks 忽略前导的空白区域
-d, --dictionary-order 只考虑空白区域和字母字符
-f, --ignore-case 忽略字母大小写
-g, --general-numeric-sort 按照常规数值排序
-i, --ignore-nonprinting 只排序可打印字符
-n, --numeric-sort 根据字符串数值比较(整个字符串的字典序)
-r, --reverse 逆序输出排序结果

其他选项:

-c, --check, --check=diagnose-first 检查输入是否已排序,若已有序则不进行操作
-k, --key=位置1[,位置2] 在位置1 开始一个key,在位置2 终止(默认为行尾)
-m, --merge 合并已排序的文件,不再进行排序
-o, --output=文件 将结果写入到文件而非标准输出
-t, --field-separator=分隔符 使用指定的分隔符代替非空格到空格的转换
-u, --unique 配合-c,严格校验排序;不配合-c,则只输出一次排序结果

sort的单位是每一行。

用法示例

将a.txt中的每一行按照字典序排序
cat a.txt | sort
将a.txt中的每一行,按照常规数字排序,支持科学计数法
cat a.txt | sort -g
将a.txt中的每一行排序并去重
cat a.txt | sort -u

uniq

uniq 命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用。

uniq 语法

-c: 在每列旁边显示该行重复出现的次数。

-d: 仅显示重复出现的行列,显示一行。

-D: 显示所有重复出现的行列,有几行显示几行。

-u: 仅显示出一次的行列

-i: 忽略大小写字符的不同

-f Fields: 忽略比较指定的列数。

-s N: 忽略比较前面的N个字符。
-w N: 对每行第N个字符以后的内容不作比较。

用法示例

对a.txt文本直接去重
cat a.txt | uniq 
对a.txt文本去重后旁边显示出现次数 
cat a.txt | uniq -c 

awk

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk内置变量

ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,…以此类推。
$NF是number finally,表示最后一列的信息,跟变量NF是有区别的,变量NF统计的是每行列的总数

awk常用语法

用途 输入文本 a.txt 命令 输出文本
筛选包含关键字的行 a b c
c d f
b a g
awk ‘/b/’ a.txt a b c
b a g
筛选包含关键字的行
并输出某一列
a b c
c d f
b a g
awk ‘/b/ {print $2}’ a.txt b
a
使用printf输出,更清晰 a b c
c d f
b a g
awk ‘/b/ {printf ("%s\n",$2)}’ a.txt b
a
只保留第二行信息 a b c
c d f
b a g
awk ‘NR==2 {printf ("%s",$2)}’ a.txt c d f
设置特定的分隔符并输出第一列 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{printf ("%s",$2)}’ a.txt b
d
a
设置特定的分隔符并输出最后一列 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{printf ("%s",$NF)}’ a.txt c
f
g
设置特定的分隔符并输出倒数第二列 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{printf ("%s",$NF-1)}’ a.txt b
d
a
获取第二到第三行的第一列信息 a : b : c
c : d : f
b : a : g
awk -F ‘:’ ‘{if(NR>=2&&NR<=3) print $1}’ a.txt c
b
多个分隔符 1:2?3,4 awk -F ‘[,:?]’ ‘{print $4}’ words.txt 4
发布了299 篇原创文章 · 获赞 117 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/104733422