该系列是基于牛客Shell题库,针对具体题目进行查漏补缺,学习相应的命令。
刷题链接:牛客题霸-Shell篇。
该系列文章都放到专栏下,专栏链接为:《专栏:Shell》。欢迎关注专栏~
本文知识预告:
- 本文首先学习了正则表达式和
awk
命令的相关的用法;
- 然后,给出了三种题目的解决方案,基本算是前面题目都用到过的知识点。
假设有一个nowcoder.txt,编写脚本,打印只有一个数字的行。假设nowcoder.txt内容如下:
haha
1
2ab
cd
那么你的脚本应该输出
1
2ab
相关命令学习
正则表达式
正则表达式为高级的文本模式匹配、抽取、与/或文本形式的搜索和替换功能提供了基础。简单地说,正则表达式是一些由字符和特殊符号组成的字符串,它们描述了模式的重复或者表述多个字符,于是正则表达式能按照某种模式匹配一系列有相似特征的字符串。
正则表达式的强大之处在于引入特殊字符来定义字符集、匹配子组和重复模式。正是由于这些特殊符号,使得正则表达式可以匹配字符串集合,而不仅仅只是某单个字符串。下面列出最常见的符号和字符。
常见的符号:
表示法 |
描述 |
正则表达式示例 |
literal |
匹配文本字符串的字面值literal
|
foo |
re1\\|re2 |
匹配正则表达式re1 或者 re2
|
foo|bar |
. |
匹配任何字符(除了\\n 之外) |
b.b |
^ |
匹配字符串起始部分 |
^Dear |
$ |
匹配字符串终止部分 |
/bin/*sh$ |
* |
匹配 0 次或者多次前面出现的正则表达式 |
[A-Za-z0-9]* |
+ |
匹配 1 次或者多次前面出现的正则表达式 |
[a-z]+.com |
? |
匹配 0 次或者 1 次前面出现的正则表达式 |
goo? |
{N} |
匹配 N 次前面出现的正则表达式 |
[0-9]{3} |
{M,N} |
匹配 M~N 次前面出现的正则表达式 |
[0-9]{5,9} |
[…] |
匹配来自字符集的任意单一字符 |
[aeiou] |
[..x−y..] |
匹配 x~y 范围中的任意单一字符 |
[0-9], [A-Za-z] |
[^…] |
不匹配此字符集中出现的任何一个字符,包括某一范围的字符 |
[^aeiou], [^A-Za-z0-9] |
常见的特殊字符:
表示法 |
描述 |
正则表达式示例 |
literal |
匹配文本字符串的字面值literal
|
foo |
re1\\|re2 |
匹配正则表达式re1 或者 re2
|
foo|bar |
. |
匹配任何字符(除了\\n 之外) |
b.b |
^ |
匹配字符串起始部分 |
^Dear |
$ |
匹配字符串终止部分 |
/bin/*sh$ |
* |
匹配 0 次或者多次前面出现的正则表达式 |
[A-Za-z0-9]* |
+ |
匹配 1 次或者多次前面出现的正则表达式 |
[a-z]+.com |
? |
匹配 0 次或者 1 次前面出现的正则表达式 |
goo? |
{N} |
匹配 N 次前面出现的正则表达式 |
[0-9]{3} |
{M,N} |
匹配 M~N 次前面出现的正则表达式 |
[0-9]{5,9} |
[…] |
匹配来自字符集的任意单一字符 |
[aeiou] |
[..x−y..] |
匹配 x~y 范围中的任意单一字符 |
[0-9], [A-Za-z] |
[^…] |
不匹配此字符集中出现的任何一个字符,包括某一范围的字符 |
[^aeiou], [^A-Za-z0-9] |
awk
:文本和数据进行处理的编程语言
awk
命令来自于三位创始人”Alfred Aho,Peter Weinberger, Brian Kernighan “的姓氏缩写,其功能是用于对文本和数据进行处理的编程语言。使用awk
命令可以让用户自定义函数或正则表达式对文本内容进行高效管理,与sed
、grep
并称为Linux系统中的文本三剑客。
语法格式:awk 参数 文件
常用参数:
参数 |
功能 |
-F |
指定输入时用到的字段分隔符 |
-v |
自定义变量 |
-f |
从脚本中读取awk 命令 |
-m |
对val 值设置内在限制 |
常用的awk
内置变量:
awk
语法由一系列条件和动作组成,在花括号内可以有多个动作,多个动作之间用分号分隔,在多个条件和动作之间可以有若干空格,也可以没有。
变量名称 |
说明 |
FILENAME |
当前输入文档的文件名 |
FNR |
当前输入文档的当前行号,尤其当多个输入文档时有用 |
FS |
设置字段分隔符,默认为空格或制表符 |
NF |
当前记录(行)的字段(列)个数 |
NR |
输入数据流的当前记录数(行号) |
OFS |
输出字段分隔符,默认为空格 |
ORS |
输出记录分隔符,默认为换行符 |
RS |
输入记录分隔符,默认为换行符 |
awk
是一种处理文本文件的编程语言,文件的每行数据都被称为记录,默认以空格或制表符为分隔符,每条记录被分成若干字段(列),awk
每次从文件中读取一条记录。
题目解决方案
方法一:awk
思路很简单,以0-9
的数字做分割,判断每行有多少列,即可筛选出题目要求的内容(两列)
awk -F "[0-9]" '{if(NF==2) print $0}' nowcoder.txt
方法二:正则表达式
结合上面给出的正则表达式的用法,根据这道题目,可以利用正则表达式匹配出我们所需要的内容:
- 以数字开头,非数字结尾
'^[0-9]([a-zA-z]+)$'
- 以字母开头,数字结尾
'^([z-zA-Z])*[0-9]$'
- 以字母开头,字母结尾,中间一个数字
'^([a-zA-Z])*[0-9]([a-zA-Z])*$'
所以题目的解决方案为:
awk '/(^[0-9]([a-z]+)$)|(^[a-z]*[0-9]$)|(^[a-z][0-9][a-z]$)/' nowcoder.txt
方法三:while
while read line; do
let count=0
for ((i = 0; i < ${#line}; i++)); do
[[ ${line:i:1} =~ [0-9] ]] && ((count++))
done
if [ $count -eq 1 ]; then
printf "$line\n"
fi
done <nowcoder.txt