MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Bash中的查找与排序命令

2021-04-127.8k 阅读

1. 查找命令之 grep

grep 是一个在文本文件中查找匹配指定模式字符串的强大工具,它在 Bash 脚本编写以及日常系统管理中使用频率极高。其基本语法为:

grep [options] pattern [file ...]
  • 简单匹配:假设我们有一个名为 example.txt 的文件,内容如下:
apple
banana
cherry
date

要在该文件中查找包含 “ana” 的行,可以使用以下命令:

grep ana example.txt

输出结果将是:

banana
  • 忽略大小写匹配:使用 -i 选项,例如查找 “APPLE”,即使文件中的 “apple” 是小写,也能匹配到:
grep -i APPLE example.txt

输出:

apple
  • 显示行号:使用 -n 选项可以显示匹配行在文件中的行号。例如:
grep -n ana example.txt

输出:

2:banana
  • 递归查找目录下所有文件:使用 -r 选项,假设在当前目录下有一个 subdir 目录,其中也有文本文件。要在整个目录树中查找匹配模式,可执行:
grep -r ana .

这里的 . 表示当前目录。这个命令会递归地在当前目录及其子目录下的所有文件中查找 “ana” 模式,并输出匹配的行。

  • 只输出匹配的部分:使用 -o 选项,例如在 “banana” 中只想输出匹配的 “ana”:
grep -o ana example.txt

输出:

ana
  • 反向匹配:使用 -v 选项,查找不包含指定模式的行。比如查找不包含 “ana” 的行:
grep -v ana example.txt

输出:

apple
cherry
date

2. 查找命令之 find

find 命令用于在文件系统中查找文件和目录,与 grep 主要针对文本内容不同,find 更侧重于文件系统层面的查找。其基本语法为:

find [path ...] [expression]
  • 按文件名查找:在当前目录及其子目录下查找名为 test.txt 的文件:
find . -name test.txt

这里 . 是查找的起始路径,-name 是按文件名匹配的表达式。如果文件名包含通配符,例如要查找所有以 .txt 结尾的文件:

find . -name "*.txt"
  • 按文件类型查找:使用 -type 选项,例如只查找目录:
find . -type d

d 表示目录类型,若要查找普通文件则使用 f

find . -type f
  • 按文件大小查找:使用 -size 选项,例如查找大于 10KB 的文件(k 表示千字节,M 表示兆字节,G 表示吉字节):
find . -type f -size +10k

要查找小于 10KB 的文件则是:

find . -type f -size -10k
  • 按文件修改时间查找
    • -mmin:按分钟查找修改时间。例如查找在过去 60 分钟内修改过的文件:
find . -type f -mmin -60
  • -mtime:按天查找修改时间。查找在过去 3 天内修改过的文件:
find . -type f -mtime -3
  • 结合多个条件查找:可以使用逻辑运算符 -a(与)、-o(或)。例如查找名为 test.txt 且大小大于 10KB 的文件:
find . -name test.txt -a -type f -size +10k

查找名为 test.txt 或者大小大于 10KB 的文件:

find . -name test.txt -o -type f -size +10k

3. 排序命令之 sort

sort 命令用于对文本文件的行进行排序,它可以按照不同的规则进行排序。基本语法为:

sort [options] [file ...]
  • 默认排序:假设我们有一个文件 sort_example.txt,内容如下:
banana
apple
cherry

执行 sort sort_example.txt,输出结果将是:

apple
banana
cherry

默认情况下,sort 命令按字典序对行进行排序。

  • 按数字排序:如果文件内容是数字,默认的字典序排序可能不符合预期。例如文件 numbers.txt 内容为:
10
2
15

执行 sort numbers.txt 会得到:

10
15
2

这是按字典序排序的结果。要按数字大小排序,使用 -n 选项:

sort -n numbers.txt

输出:

2
10
15
  • 反向排序:使用 -r 选项可以进行反向排序。对于上述按数字排序的结果,如果要反向排序:
sort -nr numbers.txt

输出:

15
10
2
  • 按字段排序:当文件内容是由多个字段组成,以空格或制表符分隔时,可以按指定字段排序。假设文件 fields.txt 内容如下:
apple 10 20
banana 5 15
cherry 12 25

要按第二个字段排序,使用 -k 选项:

sort -k2 fields.txt

输出:

banana 5 15
apple 10 20
cherry 12 25
  • 忽略大小写排序:使用 -f 选项,例如文件 mixed_case.txt 内容为:
Apple
banana
Cherry

执行 sort -f mixed_case.txt,输出:

Apple
banana
Cherry

会将大小写视为相同进行排序。

4. 查找与排序命令的结合使用

在实际应用中,经常需要将查找命令和排序命令结合起来以达到更复杂的需求。

  • 查找并排序匹配内容:例如,在一个日志文件 log.txt 中查找所有包含 “error” 的行,并按行号排序(假设日志文件每行开头有行号)。首先使用 grep 查找包含 “error” 的行,然后通过管道将结果传递给 sort 进行排序。假设 log.txt 内容如下:
1 INFO Starting application
2 ERROR Connection failed
3 INFO Application running
4 ERROR Authentication failed

执行以下命令:

grep error log.txt | sort -n

输出:

2 ERROR Connection failed
4 ERROR Authentication failed
  • 查找文件并按文件大小排序:先使用 find 查找当前目录下所有普通文件,然后按文件大小排序。可以使用如下命令:
find . -type f -exec du -h {} + | sort -h

这里 du -h 用于获取文件大小,-exec 选项让 find 对每个找到的文件执行 du -h 命令,然后将结果通过管道传递给 sort,-h 选项使 sort 按人类可读的大小格式进行排序。

5. 高级查找与排序技巧

  • grep 的扩展正则表达式:grep 有两种正则表达式模式,基本正则表达式(BRE)和扩展正则表达式(ERE)。默认使用 BRE,要使用 ERE 需加上 -E 选项。例如,假设要查找包含 “apple” 或 “banana” 的行,在 ERE 中可以这样写:
grep -E 'apple|banana' example.txt

在 BRE 中,| 不是一个特殊字符,所以要实现同样功能会复杂一些。

  • find 的深度限制:在使用 find 递归查找目录时,有时不希望查找过深的目录层次。可以使用 -maxdepth 选项来限制查找深度。例如,只在当前目录下一层子目录中查找文件:
find . -maxdepth 2 -type f

这里 -maxdepth 2 表示查找深度最大为 2 层(包括当前目录)。

  • sort 的稳定排序:默认情况下,sort 命令是不稳定的,即相同排序键的行顺序可能会改变。如果需要稳定排序,可以使用 -s 选项。例如对一个包含重复数字的文件 stable.txt 进行稳定排序:
sort -sn stable.txt

这样相同数字的行在输出中会保持原来的相对顺序。

6. 查找与排序命令在脚本中的应用

  • 在 Bash 脚本中使用 grep 进行配置文件检查:假设我们有一个配置文件 config.ini,需要检查其中是否配置了特定的服务器地址。以下是一个简单的 Bash 脚本示例:
#!/bin/bash

if grep -q "server_address = 192.168.1.100" config.ini; then
    echo "Server address is correctly configured."
else
    echo "Server address is not configured or incorrect."
fi

这里 -q 选项使 grep 安静运行,不输出匹配的行,只返回状态码。脚本根据 grep 的返回状态码判断配置是否正确。

  • 在脚本中使用 find 进行文件管理:编写一个脚本,查找当前目录下所有超过 30 天未修改的文件,并将其移动到 old_files 目录(假设 old_files 目录已存在):
#!/bin/bash

find . -type f -mtime +30 -exec mv {} old_files/ \;
  • 在脚本中结合 sort 进行数据处理:假设我们有一个包含学生成绩的文件 grades.txt,格式为 “学生姓名 成绩”,需要对成绩进行排序并输出。以下是脚本示例:
#!/bin/bash

sort -nrk2 grades.txt

这个脚本直接对 grades.txt 文件按成绩(第二字段)进行反向数字排序并输出。

7. 查找与排序命令的性能优化

  • grep 的性能优化
    • 减少数据量:如果只需要在文件的部分内容中查找,可以使用工具如 headtail 先获取部分数据再进行 grep 操作。例如,如果只需要在文件前 100 行中查找,可以这样:
head -n 100 file.txt | grep pattern
  • 使用固定字符串匹配:如果要查找的是固定字符串而非正则表达式,使用 -F 选项可以提高性能。例如:
grep -F "specific_string" file.txt
  • find 的性能优化
    • 限制查找范围:尽量精确指定查找的起始路径和深度,避免在不必要的目录树中查找。例如,如果只需要在 /var/log 目录及其下一层子目录查找,可以这样:
find /var/log -maxdepth 2 -type f
  • 合理使用缓存:在一些系统中,locate 命令利用系统文件缓存来查找文件,比 find 更快速,但它不是实时更新的。如果不需要实时查找,可以先尝试使用 locate。例如:
locate test.txt
  • sort 的性能优化
    • 内存使用控制:对于非常大的文件排序,可以通过 -S 选项指定排序时使用的内存大小。例如,如果系统内存有限,可指定使用 100MB 内存进行排序:
sort -S 100M large_file.txt
  • 提前预处理:如果文件中有大量无关信息,可以先使用工具如 sedawk 去除这些信息后再进行排序,以减少排序的数据量。例如,去除文件中的注释行后再排序:
sed '/^#/d' file.txt | sort

这里 sed '/^#/d' 用于删除以 # 开头的注释行,然后将处理后的内容传递给 sort 进行排序。

通过深入理解和灵活运用这些查找与排序命令,我们可以更高效地处理文本数据和文件系统操作,无论是在日常系统管理还是在复杂的脚本编写中,都能大大提高工作效率。在实际应用中,要根据具体需求选择合适的命令和选项,并注意性能优化,以达到最佳的使用效果。