shell编程练习(一)
1
给定一个文本文件 file.txt
,请只打印这个文件中的第十行。
示例:
假设 file.txt
有如下内容:
Line 1 |
你的脚本应当显示第十行:
Line 10 |
解:
sed -n '10p' file.txt |
-n 指除了第十行都不打印
awk 'NR == 10' file.txt |
NR
是 awk
内置的一个变量,表示当前处理的行号(行号从1开始)。这个模式表示如果当前行号等于10,则匹配成功。
tail -n +10 file.txt | head -1 |
tail -n +10 从文件的第十行开始打印,head -1 从头开始打印一行
2
给定一个包含电话号码列表(一行一个电话号码)的文本文件 file.txt
,写一个单行 bash 脚本输出所有有效的电话号码。
你可以假设一个有效的电话号码必须满足以下两种格式: (xxx) xxx-xxxx 或 xxx-xxx-xxxx。(x 表示一个数字)
你也可以假设每行前后没有多余的空格字符。
示例:
假设 file.txt
内容如下:
987-123-4567 |
你的脚本应当输出下列有效的电话号码:
987-123-4567 |
解:
grep -E '^(\([0-9]{3}\) |[0-9]{3}-)[0-9]{3}-[0-9]{4}$' file.txt |
-E 启用正则表达式
^
: 匹配行的开始。\(
: 匹配左括号(
。[0-9]{3}
: 匹配三个数字。\)
或者 ``: 匹配右括号)
或者空格。| 表示或者
(\([0-9]{3}\) |[0-9]{3}-)
[0-9]{3}
: 匹配三个数字。-
: 匹配短横线-
。[0-9]{4}
: 匹配四个数字。$
: 匹配行的结尾。
3
给定一个文件 file.txt
,转置它的内容。
你可以假设每行列数相同,并且每个字段由 ' '
分隔。
示例:
假设 file.txt
文件内容如下:
name age |
应当输出:
name alice ryan |
解:
columns=$(cat file.txt | head -n 1 | wc -w) |
wc -w 统计单词数
$(seq 1 $columns) 表示循环列数,seq用于生成1-seq的数字,seq 1表示生成数字1
awk ‘{print $’$i’}’ 是一个动态引用,print $i 表示打印每行的第几个字段
xargs 逐列将每列转换为行。但是这里我们只需要每次取一列所以需要前置处理
4
写一个 bash 脚本以统计一个文本文件 words.txt
中每个单词出现的
频率
为了简单起见,你可以假设:
words.txt
只包括小写字母和' '
。- 每个单词只由小写字母组成。
- 单词间由一个或多个空格字符分隔。
示例:
假设 words.txt
内容如下:
the day is sunny the the |
你的脚本应当输出(以词频降序排列):
the 4 |
说明:
- 不要担心词频相同的单词的排序问题,每个单词出现的频率都是唯一的。
- 你可以使用一行 Unix pipes 实现吗?
解:
awk '{for(i=1; i<=NF; i++) {count[$i]++;}} END {for(word in count) {print word, count[word];}}' words.txt | sort -k2,2nr |
awk可以逐行读取每行的单词,NF表示每行的字段数,以单词($i)作为索引来建立计数数组
sort -k2,2nr
对输入进行排序。具体参数含义如下:
-k2,2nr
表示按照第二列(单词出现的次数)进行逆序排序。2,2表示从第二列到第二列-n
表示按照数值大小排序。-r
表示逆序排序。
cat words.txt | tr -s ' ' '\n' | sort | uniq -c | sort -r | awk '{ print $2, $1 }' |
tr -s ' ' '\n'
:tr
命令用于字符替换,-s ' '
表示将多个连续的空格字符替换成一个空格,'\n'
表示将空格替换成换行符,因此这一步将文本中的空格分隔的单词转换成每行一个单词的形式。sort
:对单词进行排序。uniq -c
:uniq
命令用于去除连续重复的行,-c
选项会显示每行重复出现的次数。因此,这一步会统计每个单词出现的次数。sort -r
:对统计结果按照出现次数进行逆序排序。