当前位置: 首页 > news >正文

Linux小课堂: 数据处理核心命令之grep、sort、wc、uniq 与 cut 的深度解析

文本搜索利器:grep 命令的全面掌握

grep 是 Linux 系统中最强大且使用最频繁的文本过滤工具之一,其名称来源于 global search for a regular expression and print(全局正则表达式匹配并打印)的缩写。它的核心功能是在文件中查找包含指定字符串或模式的行,并将这些行输出到终端。

1 ) 基本语法与用法

grep [选项] 搜索文本 文件路径

grep [option] "pattern" file 
  • pattern:要搜索的字符串或正则表达式
  • file:目标文件路径

例如,在 /etc/profile 配置文件中查找所有包含 "pass" 字符串的行:

grep pass /etc/profile

执行后,终端会列出所有包含 pass 的行,并以高亮颜色(通常是红色)标注关键词。

注意:若搜索文本中含有空格,必须使用双引号包裹,如:

grep "hello world" profile.txt

2 )关键参数详解

-i:忽略大小写(ignore case)
默认情况下,grep 区分大小写。添加 -i 参数可实现不区分大小写的搜索。

grep -i pass /etc/profile 

此命令将匹配 passPassPASSPaSs 等多种形式。

-n:显示行号(number lines)
通过 -n 参数可以显示匹配行在文件中的行号,便于定位:

grep -n pass /etc/profile 

输出示例:

11: PATH=$PATH:/usr/local/bin
38: export PASSWD=xxx

-v:反向筛选(invert match)
使用 -v 参数时,grep 将只输出不包含指定文本的行,相当于“排除”操作。

grep -v pass /etc/profile

该命令将显示所有不含 pass 的行,常用于日志清洗和异常排查。

-r:递归搜索目录(recursive)
当不确定目标文本位于哪个子文件中时,可使用 -r 参数对整个目录树进行递归搜索。

grep -r "helloworld" ./folder/

这将在 folder/ 目录及其所有子目录中查找包含 helloworld 的文件。

提示:rgrep 命令等价于 grep -r,但部分系统已弃用,建议直接使用 grep -r

3 )高级用法:结合正则表达式(Regular Expression)

为了支持复杂的模式匹配,需启用扩展正则表达式(Extended Regular Expressions),使用 -E 参数(或使用 egrep 命令):

grep -E 'pattern' file 

或使用别名命令 egrep,效果相同

常用正则符号表

符号含义说明
.匹配任意单个字符(换行符除外)
^匹配行首
$匹配行尾
[abc]匹配方括号内的任意一个字符
[a-z]匹配小写字母范围
[A-Z]匹配大写字母范围
[0-9]匹配数字范围
?前一项出现 0 次或 1 次
*前一项出现 0 次或多次
+前一项至少出现 1 次
``
( )分组,定义优先级

实战示例

  1. 查找以 PATH 开头的行:
grep -E '^PATH' /etc/profile
  1. 匹配 PATHpath(即 P 大写或小写):
grep -E '^[Pp]ATH' /etc/profile
  1. 查找包含 0 到 4 之间任意数字的行:
grep -E '[0-4]' /etc/profile
  1. 查找包含任意字母(大小写均可)的行:
grep -E '[a-zA-Z]' /etc/profile 

跨平台兼容性提示:尽管某些 Linux 发行版(如 CentOS)默认激活正则功能,但为确保脚本可移植性,始终推荐显式使用 -E 参数。

排序工具:sort 命令的灵活运用

sort 命令用于对文本行进行排序,底层基于高效的排序算法(如快速排序、归并排序),适用于结构化数据整理,默认按字典序升序排列

1 )基础排序操作

创建测试文件 name.txt 并填入若干英文名:

nano name.txt
输入内容如下:
Alice 
Bob
Charlie
David 
Eve
Frank 
Grace
Henry 
Ivy

执行基础排序:

sort name.txt

结果按字母顺序排列,不区分大小写影响相对位置。

2 ) 核心参数详解

-o:输出至新文件(output)
sort 默认仅在终端显示结果,不会修改原文件。使用 -o 可将排序结果保存到指定文件:

sort -o names_sorted.txt name.txt

原文件 names.txt 内容不变,排序结果存入 names_sorted.txt

-r:倒序排列(reverse)
实现降序排列,字母从 Z 到 A:

sort -r name.txt

-R:随机排序(random)
使用大写的 -R 参数可使每轮排序结果随机化,适合打乱顺序场景:

sort -R name.txt

多次运行将产生不同顺序,适用于抽奖、抽样等需求。

-n:数值排序(numeric sort)
默认排序将数字视为字符串处理(字典序),导致 100 排在 2 前面。使用 -n 实现真正的数值排序:

创建数字文件
nano numbers.txt
内容:
100
25
3
87
12 字符串排序(错误)
sort numbers.txt
输出:100, 12, 25, 3, 87 正确数值排序
sort -n numbers.txt
输出:3, 12, 25, 87, 100

统计分析:wc 命令精准计数

wc(word count)是多功能统计工具,可用于计算行数、单词数、字符数及字节数

1 ) 基本输出格式

wc name.txt

输出格式为三列数字:

<lines> <words> <bytes> filename.txt

输出三个数值:行数 单词数 字节数 文件名

示例:

9 9 50 name.txt

解释:

  • 第一个 9:共 9 行(每行末尾 \n 计为换行)
  • 第二个 9:每行一个名字,共 9 个单词(由空格分隔的非空字符串)
  • 第三个 50:总字节数 = 字符数 + 换行符占用字节
    如:9 个名字共 41 字符 + 9 个 \n = 50 字节

2 ) 精细化统计参数

参数功能示例
-l统计行数(lines)wc -l name.txt9
-w统计单词数(words)wc -w name.txt9
-c统计字节数(bytes)wc -c name.txt50
-m统计字符数(characters)wc -m name.txt50(ASCII 下与 -c 相同)

注:

  • -c 中的 c 应理解为 “count of bytes”,或可能源自 “character” 或早期 Unix 命名习惯;虽非直观缩写,但在 POSIX 标准中固定存在
  • -m 对 Unicode 多字节字符更准确,来自 “multibyte character”

去重处理:uniq 命令的局限与突破

uniq 用于删除相邻重复行,前提是数据已排序(否则无法识别非连续重复项),或将重复内容可视化

1 ) 基本用法

创建含重复内容的文件 repeat.txt

nano repeat.txt
内容:
Albert 
France
France
France
Mater 
Mater
Zoe

执行去重:

uniq repeat.txt

输出:

Albert 
France
Mater
Zoe

重要限制:uniq 只能处理连续重复行,若未排序则无效。应配合 sort 先排序再去重:

sort repeat.txt | uniq

2 ) 扩展参数应用

-c:统计重复次数(count)
显示每行出现的频次:

uniq -c repeat.txt

输出:

     1 Albert 3 France 2 Mater 1 Zoe 

-d:仅显示重复行(duplicated)
只输出出现了两次以上的行:

uniq -d repeat.txt

输出:

France
Mater

便于快速定位高频项

-u 参数:仅显示唯一行(Unique Only)

uniq -u repeat.txt

输出:

Albert
Eve

持久化保存结果:

uniq repeat.txt unique.txt  # 输出到文件

实用组合:统计并筛选高频词

sort log.txt | uniq -c | sort -nr | head -10 

上述命令链实现日志中访问最多的前 10 条记录提取

字段剪切:cut 命令精确提取列数据

cut 用于从每行中截取特定位置的内容,适用于 CSV、日志等定长或分隔格式数据。

1 ) 按字符位置剪切(-c)
保留每行第 2 到第 4 个字符:

cut -c 2-4 name.txt

输入 Alice → 输出 lic

支持多种格式:

  • cut -c 1-3:前 3 字符
  • cut -c 5-:从第 5 字符开始到结尾
  • cut -c 2,5:第 2 和第 5 字符

2 ) 按字段分隔符剪切(-f 与 -d)

对于 tab 或逗号分隔的数据,使用:

cut -d',' -f2 data.csv  # 以逗号分隔,提取第2字段

示例 CSV 文件:

name,age,city
Alice,25,Beijing
Bob,30,Shanghai
cut -d',' -f1,3 data.csv
输出:
name,city
Alice,Beijing
Bob,Shanghai

模拟 Linux 文本处理管道示例


1 ) 方案1

以下是一个基于 NestJS 的服务模块,模拟 grepsortwcuniqcut 的核心逻辑,体现函数式编程思想与流式处理能力。

// text-processing.service.ts
import { Injectable } from '@nestjs/common';@Injectable()
export class TextProcessingService {/* grep 模拟:支持正则、忽略大小写、反向匹配*/grep(lines: string[],pattern: string,options: { ignoreCase?: boolean; invert?: boolean; useRegex?: boolean } = {},): string[] {const flags = options.ignoreCase ? 'gi' : 'g';const regex = options.useRegex? new RegExp(pattern, flags): new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), flags);return lines.filter(line => {const matches = regex.test(line);return options.invert ? !matches : matches;});}/* sort 模拟:支持字母、数字、倒序、随机排序*/sort(lines: string[],options: { numeric?: boolean; reverse?: boolean; random?: boolean } = {},): string[] {let result = [...lines];if (options.random) {return result.sort(() => Math.random() - 0.5);}result.sort((a, b) => {if (options.numeric) {const numA = parseFloat(a) || 0;const numB = parseFloat(b) || 0;return numA - numB;}return a.localeCompare(b);});if (options.reverse) {result.reverse();}return result;}/* wc 模拟:统计行数、单词数、字节数*/wc(content: string): { lines: number; words: number; bytes: number; chars: number } {const lines = content.split('\n').length;const words = content.trim().split(/\s+/).filter(Boolean).length;const chars = content.length;const bytes = new Blob([content]).size;return { lines, words, bytes, chars };}/* uniq 模拟:去重、计数、仅重复项*/uniq(lines: string[],options: { count?: boolean; duplicatesOnly?: boolean } = {},): (string | { count: number; line: string })[] {const result: any[] = [];let currentLine = null;let count = 0;for (const line of lines) {if (line === currentLine) {count++;} else {if (currentLine !== null) {const item = options.count? { line: currentLine, count }: currentLine;if (!options.duplicatesOnly || count > 1) {result.push(item);}}currentLine = line;count = 1;}}// 最后一行if (currentLine !== null) {const item = options.count? { line: currentLine, count }: currentLine;if (!options.duplicatesOnly || count > 1) {result.push(item);}}return result;}/* cut 模拟:按字符或字段切割*/cutByChar(lines: string[], start: number, end?: number): string[] {return lines.map(line => {if (end) return line.slice(start - 1, end);return line.charAt(start - 1);});}cutByField(lines: string[], delimiter: string, fields: number[]): string[] {return lines.map(line => {const parts = line.split(delimiter);return fields.map(f => parts[f - 1] || '').join(delimiter);});}
}

控制器调用示例

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { TextProcessingService } from './text-processing.service';@Controller('linux')
export class AppController {constructor(private readonly tp: TextProcessingService) {}@Get('demo')demo() {const data = ['apple','Banana','apple','Cherry','banana','Apple'];const filtered = this.tp.grep(data, 'apple', { ignoreCase: true });const sorted = this.tp.sort(filtered, { reverse: true });const unique = this.tp.uniq(sorted, { count: true });return { original: data, filtered, sorted, unique };}
}

2 )方案2

模拟上述 Linux 命令行为,实现日志文件的读取、搜索、排序、统计与清洗功能。

// log-analyzer.service.ts
import { Injectable } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';@Injectable()
export class LogAnalyzerService {private readonly basePath = '/var/logs'; // 模拟日志目录 /* grep 模拟:搜索关键词(支持正则)*/grep(filePath: string, pattern: string, flags: 'i' | 'v' | '' = ''): string[] {const content = fs.readFileSync(path.join(this.basePath, filePath), 'utf-8');const lines = content.split('\n');const regexFlags = flags.includes('i') ? 'gi' : 'g';const regex = new RegExp(pattern, regexFlags);return lines.filter(line => {const hasMatch = regex.test(line);return flags.includes('v') ? !hasMatch : hasMatch;});}/* sort 模拟:排序(支持数值、倒序)*/sort(lines: string[], numeric = false, reverse = false): string[] {const sorted = [...lines].sort((a, b) => {if (numeric) {const numA = parseFloat(a) || 0;const numB = parseFloat(b) || 0;return numA - numB;}return a.localeCompare(b);});return reverse ? sorted.reverse() : sorted;}/* wc 模拟:统计行数、单词数、字节数*/wc(content: string): { lines: number; words: number; bytes: number } {const lines = content.split('\n').length;const words = content.trim().split(/\s+/).filter(Boolean).length;const bytes = Buffer.byteLength(content, 'utf-8');return { lines, words, bytes };}/* uniq 模拟:去重并统计*/uniq(lines: string[], options: { count?: boolean; duplicatesOnly?: boolean }): string[] | Record<string, number> {const result: Record<string, number> = {};lines.forEach(line => {result[line] = (result[line] || 0) + 1;});if (options.count) {return Object.entries(result).map(([line, count]) => `${count} ${line}`);}if (options.duplicatesOnly) {return Object.keys(result).filter(line => result[line] > 1);}return Object.keys(result);}/* cut 模拟:按字符范围截取*/cutByChar(lines: string[], start: number, end: number): string[] {return lines.map(line => line.substring(start - 1, end));}/* 完整流程演示:分析日志中的 IP 地址频率 */analyzeLogIps(logFile: string): Record<string, number> {const ips = this.grep(logFile, '\\b(?:\\d{1,3}\\.){3}\\d{1,3}\\b', '') // 提取IP.map(line => line.match(/\b(?:\d{1,3}\.){3}\d{1,3}\b/)?.[0]).filter(Boolean);const frequency: Record<string, number> = {};ips.forEach(ip => {frequency[ip] = (frequency[ip] || 0) + 1;});return frequency;}
}

控制器调用示例

// log.controller.ts
import { Controller, Get, Query } from '@nestjs/common';
import { LogAnalyzerService } from './log-analyzer.service';@Controller('logs')
export class LogController {constructor(private readonly analyzer: LogAnalyzerService) {}@Get('search')search(@Query('file') file, @Query('pattern') pattern) {return this.analyzer.grep(file, pattern);}@Get('stats')stats(@Query('file') file) {const content = fs.readFileSync(`/var/logs/${file}`, 'utf-8');return this.analyzer.wc(content);}
}

3 )方案3

用于服务器端文本处理:

// text-processing.service.ts
import { Injectable } from '@nestjs/common';@Injectable()
export class TextProcessingService {/* 模拟 grep 功能:支持正则、忽略大小写、反向匹配 */grep(content: string[],pattern: string,options: { ignoreCase?: boolean; invert?: boolean; useRegex?: boolean } = {},): string[] {const flags = options.ignoreCase ? 'gi' : 'g';const regex = options.useRegex? new RegExp(pattern, flags): new RegExp(pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), flags);return content.filter(line => {const matches = regex.test(line);return options.invert ? !matches : matches;});}/* 模拟 sort 功能:支持字母、数字、倒序排序*/sort(content: string[],options: { numeric?: boolean; reverse?: boolean } = {},): string[] {let sorted = [...content];sorted.sort((a, b) => {if (options.numeric) {const numA = parseFloat(a.trim()) || 0;const numB = parseFloat(b.trim()) || 0;return numA - numB;}return a.localeCompare(b);});if (options.reverse) sorted.reverse();return sorted;}/* 模拟 wc 功能*/wc(content: string[]): { lines: number; words: number; bytes: number } {const lines = content.length;const words = content.map(line => line.trim().split(/\s+/).filter(Boolean).length).reduce((a, b) => a + b, 0);const bytes = content.map(line => new Blob([line + '\n']).size).reduce((a, b) => a + b, 0);return { lines, words, bytes };}/* 模拟 uniq 功能*/uniq(content: string[], options: { count?: boolean; duplicatesOnly?: boolean } = {}): (string | { count: number; line: string })[] {const result: any[] = [];let currentLine = null;let count = 0;for (const line of content) {if (line === currentLine) {count++;} else {if (currentLine !== null) {const item = options.count ? { count, line: currentLine } : currentLine;if (!options.duplicatesOnly || count > 1) result.push(item);}currentLine = line;count = 1;}}if (currentLine !== null) {const item = options.count ? { count, line: currentLine } : currentLine;if (!options.duplicatesOnly || count > 1) result.push(item);}return result;}/* 模拟 cut -c 功能*/cutByChar(content: string[], start: number, end: number): string[] {return content.map(line => line.substring(start - 1, end));}
}

控制器调用示例:

// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { TextProcessingService } from './text-processing.service';@Controller('text')
export class TextController {constructor(private readonly processor: TextProcessingService) {}@Get('demo')demo() {const lines = ['export PATH=/usr/bin','export pass=123456','USER=admin','PASSWORD=secret','PATH=/bin:/sbin'];const grepResult = this.processor.grep(lines, 'pass', { ignoreCase: true });const sorted = this.processor.sort(['3', '100', '25'], { numeric: true });const stats = this.processor.wc(lines);const cutResult = this.processor.cutByChar(['Alice', 'Bob'], 2, 4);return { grepResult, sorted, stats, cutResult };}
}

构建高效数据处理流水线


命令核心用途关键参数典型应用场景
grep文本搜索与过滤-i, -n, -v, -r, -E日志排查、配置检索、正则匹配
sort行排序-n, -r, -R, -o数据排序、去重预处理、随机抽样
wc统计分析-l, -w, -c, -m文件规模评估、自动化监控、审计、容量评估
uniq去重与频次分析-c, -d, -u日志聚合、访问统计、异常检测、清洗脏数据、频次统计
cut字段提取-c, -f, -d日志解析、报表生成、ETL 清洗、CSV 字段抽取

最佳实践建议:将多个命令通过管道符 | 连接,形成处理链:

cat access.log \| grep "404" \| cut -d' ' -f1 \| sort \| uniq -c \| sort -nr \| head -10

以上命令链实现了:提取所有 404 错误日志 → 获取 IP 地址 → 排序去重 → 统计频次 → 降序排列 → 显示 Top 10 攻击源 IP

所有命令均不对原始文件做修改,可通过重定向 > 或管道 | 构建复杂数据流水线:

grep "error" app.log | sort | uniq -c | sort -nr > summary.txt

grep "error" log.txt | sort | uniq -c | sort -nr | cut -f2-

这五个命令可通过管道无缝衔接,构成强大的文本处理流水线:
实现:找出错误日志 → 排序 → 统计频次 → 按频率降序 → 提取消息内容

最终结论:掌握 grepsortwcuniqcut 不仅是 Linux 基础技能,更是构建自动化运维、日志分析、大数据预处理系统的基石

http://www.dtcms.com/a/509552.html

相关文章:

  • 深圳建筑设计平台网站wordpress wp posts
  • 北京住房和城乡建设官方网站色彩搭配比较好的网站
  • 找到网站后台地址如何做自己网站
  • 有没有人做网站大学做html个人网站素材
  • 嘉兴五县两区网站建设局机关网站建设
  • 江苏省交通建设厅门户网站wordpress如何修改首页文件模板
  • 如何建立一个网站详细步骤通辽住房和城乡建设厅网站
  • 网站设计需要多少钱小程序开发教程 下载
  • 公司无网站无平台怎么做外贸2021最火关键词
  • 手机网站的静态页面官网站站
  • 蒙古网站后缀国内知名设计工作室
  • 单页网站怎么制作昆明企业网站建设公司
  • 建设银行兰州分行网站百度小程序开发平台
  • 朝阳网站建设 慈云寺厦门易尔通网站建设好吗
  • 网站 备案 哪个省建设培训中心网站
  • 成都大型网站建设公司iis网站属性在哪
  • 中国站长查询域名备案西安有哪些做网站的公司好
  • 东莞定制网站建设jsp网站部署怎么做
  • 百度推广太原网站建设阿里云服务器添加网站
  • 2016网站优化今天深圳新增确诊最新消息
  • 驾校官方网站 模板wordpress手动装插件
  • 怎样直接输入网址打开网站ps做网站标签
  • 甘肃肃第八建设集团网站1wordpress关联adsense
  • 长沙做网站开发多少钱服务行业做网站
  • 大学生免费ppt网站长沙网站制作工作室
  • 西宁吧 百度贴吧网站优化反馈机制 seo
  • 哪些网站可以做兼职设计建网站和开发app哪个难
  • 网页制作与网站建设06627网站建设 王卫洲
  • 网站背景动图怎么做2022年新闻热点摘抄
  • 手机网站jq导航菜单网站平台建设流程