标签 shell 下的文章

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/word-frequency

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一、题目描述

写一个 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 实现吗?

二、题解

2.1 使用awk

通过NF变量遍历所有字段,存到一个哈希表(数组)中,然后打印出所有的key-value组合,最后通过sort排序。

awk '{for (i = 1; i <= NF; i++) {m[$i]++;}} END {for (i in m) {print i, m[i]}}' words.txt | sort -nr -k 2

2.2 使用xargs

通过xargs的-n参数打印出所有的字段,然后使用uniqsort对字段排序:

cat file.txt | xargs -n 1 | sort | uniq -c | sort -nr -k 2 | awk '{print $2" "$1}'
uniq的-c参数是统计词频

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/tenth-line

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

一、题目描述

给定一个文本文件 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

说明:

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

二、题解

2.1 tail+head

返回文本中的第十行,最简单的方式可以通过tail + head配合输出,通过head取到前面10行,然后输出前面10行的最后一行。很容易能想到的办法:

head -10 file.txt | tail -1

但这么做就错了,题目中已经提到如果文件少于10行,你应当输出什么?。一旦文件少于10行,上面的命令会输出文件的最后一行,不满足题意。正确的命令:

tail -n +10 file.txt | head -1

-n +10表示从第10行开始到结束,意思是先从第10行开始取到结束的所有数据然后取第一行。

2.2 sed

sed的p模式可以直接打印指定行:

sed -n '10p' file.txt

2.3 awk

awk内置变量NR表示行数

awk 'NR==10' file.txt

一、测试文件状态

shell中的测试,如果成功返回0,否则返回1。

操作符描述
-e FILE测试文件是否存在
-f FILE文件存在且是一个常规的文件为真
-d FILE文件存在且是一个目录为真
-[r,w,x] FILE文件是否可读、可写或者可执行

二、字符串比较

操作符描述
-z STR字符串为空返回真
-n STR字符串不为空返回真
STR1 = STR2字符串相等返回真
STR1 != STR2字符串不相等返回真
STR1 [<,>] STR2字符串STR1小于或者大于STR2返回真,按字典序比较

使用[]判断时,><符号需要加下划线:

> [ "abcde" \> "abcd" ] && echo "yes"
yes

使用[[]]判断时,><符号不需要加下划线:

> [[ "abcde" > "abcd" ]] && echo yes
yes

三、整数比较

操作符描述
INT2 -eq INT2两个整数相等返回真
INT1 -ne INT2两个整数不相等返回真
INT1 -[gt,ge,lt,le] INT2整数大于、大于等于、小于以及小于等于判断

四、注意事项

><符号只能用于字符串比较,不能用于整数比较。对整数使用大于小于符号比较的时候,会被当成字符串:

> [[ 53 -gt 153 ]] && echo yes
> [[ 53 > 153 ]] && echo yes
yes

一、基本用法

Makefile中执行shell命令需要在命令前面加上@,例如打印一个变量的值

KERNEL = $(shell uname -r)
INC = /usr/src/kernels/$(KERNEL)/

print:
    @echo $(KERNEL)
    @echo $(INC)

执行make print会有得到理想的输出:

2.6.32-754.6.3.el6.x86_64
/usr/src/kernels/2.6.32-754.6.3.el6.x86_64/

如果不加@符号最后的结果是:

echo 2.6.32-754.6.3.el6.x86_64
2.6.32-754.6.3.el6.x86_64
echo /usr/src/kernels/2.6.32-754.6.3.el6.x86_64/
/usr/src/kernels/2.6.32-754.6.3.el6.x86_64/

可以看到多了几行,分别把每个echo命令也打印出来了。

二、注意事项

2.1 多行命令

当shell脚本中存在多行命令时,换行时要加上\,例如:

@./configure --prefix=/usr/lib \
    aaa=1 bbb=2

2.2 把shell命令的结果赋值给Makefile变量

把shell命令的值赋值需要加上shell关键字,如:

PWD = @(shell pwd)