想在Linux里面高效处理文本?wc、awk、管道。你都得掌握!~

190 阅读4分钟

从最简单的想法开始

想象你刚接触文本处理,任务是统计一个文件有多少行。文件挺简单,比如:

hello
world
this is a test

咋办?最直白的方法是打开文件,手动数:1、2、3,行了,3 行。这种办法简单得不能再简单,但问题立马就来了——要是文件有几百行呢?手数到眼花,效率低得要命,还容易出错。更别说文件老变,你还得重新数。

于是你可能会想:“我写个脚本得了!”用 Python 敲几行:

with open('file.txt', 'r') as f:
    lines = f.readlines()
    print(len(lines))

跑一下,输出 3,搞定。但这也有坑:文件要是几百 MB 甚至 GB,readlines() 全读进内存,机器直接卡爆。而且敲代码还得费点劲,对这么简单的任务有点杀鸡用牛刀。

朴素策略的毛病暴露

手数和简单脚本这俩办法,短板太明显: 1. 效率低:手数慢得像蜗牛,脚本对大文件不友好。 2. 扩展性差:只能干一件事,想再统计单词数咋办?再写一个? 3. 灵活性不够:需求变一下,比如只数含 "test" 的行,又得从头折腾。

这些问题逼着我们去找更靠谱的办法,最好是现成的工具,不用自己从零开始。

第一步优化:单用途工具登场

这时候,Linux 的 wc -l 就派上用场了。一句 wc -l file.txt,输出 3 file.txt,快得飞起。它不像脚本那样全读内存,而是流式处理,大文件也不怕。而且它还能干别的,-w 统计单词数,-c 统计字符数,一个命令多面手,比手数和脚本强多了。

wc 也不是万能的。比如你想数含 "test" 的行,它就傻眼了。得找帮手,比如 grep "test" file.txt | wc -l,先用 grep 挑出行,再数。这组合拳靠管道(|)串起来,灵活性蹭蹭上涨。

组合工具的麻烦来了

grep | wc -l 确实好使,但需求再复杂点就有点撑不住了。假设你有个文件,每行是 名字 年龄 城市,像:

Alice 25 Beijing
Bob 30 Shanghai
Charlie 25 Tokyo

你想统计年龄是 25 的人有多少个。光靠 grep " 25 " 文件 | wc -l 不太行,因为它只能匹配整行,万一城市名里有 "25",比如 "Tokyo25",就误判了。单用途工具各干各的,逻辑稍微复杂点就显得笨拙。

走进复杂方案:awk 横空出世

这时候,awk 上场了。先聊聊它是个啥玩意儿。awk 是 Linux 里的文本处理神器,名字来自三个作者的首字母:Aho、Weinberger、Kernighan。它诞生于 1977 年,目标是让文本处理更灵活。简单说,它能按字段切分文本、做条件判断、计算啥的,像个小型编程语言。

咋用呢?看例子,统计年龄 25 的人数:

awk '$2 == 25 {count++} END {print count}' 文件

啥意思?$2 == 25 检查第 2 列(年龄)是不是 25,是的话 count 加 1,最后 END 块输出总数。跑一下,输出 2,因为 Alice 和 Charlie 都是 25 岁。它一次搞定过滤和计数,连管道都不用,多省事儿。

awk 咋记?别慌,有招

awk 看着有点怪,但记起来不难。它的基本格式是 awk '条件 {动作} END {收尾}' 文件。比如: - $1 是第 1 列,$2 是第 2 列,字段默认用空格或制表符分。 - {print $1} 打印第 1 列,{count++} 计数。 - END {print count} 在处理完所有行后输出。

记口诀:“条件判断干活儿,END 最后收拾”。多练几次,像 awk '{print $1}' 打印第 1 列,awk '/test/' 找含 "test" 的行,熟了就顺手。网上还有 cheatsheet,搜 “awk one-liner” 能找到一堆实用例子。

为啥 awk 牛?优化方向在哪

awkgrepwc 高明在哪儿?它流式处理,大文件不占内存;能写逻辑,灵活性爆棚。而且它启发了现代工具的设计。今天的大数据神器,比如 Spark、Hadoop,或者 Python 的 Pandas,都跟它有渊源。

优化方向咋对齐主流呢? 1. 流式处理awk 不全读文件,跟 Spark 的流计算一个味儿,内存友好。 2. 模块化协作:管道思想进化成了 ETL(提取-转换-加载)流程,命令间配合像数据管道。 3. 通用能力awk 的字段操作和脚本逻辑,跟 Pandas 如出一辙。

Pandas 里统计年龄 25 的人:

import pandas as pd
df = pd.read_csv('file.txt', sep=' ')
print(len(df[df['age'] == 25]))

输出 2,跟 awk 结果一样,只是更现代化,界面更亲民。

最后唠两句

从手数到 wc -l,再到 awk 和 Pandas,这一路走来,就是从简单需求出发,发现问题,再找更好办法。awk 是个关键跳板,1977 年就奠定了文本处理的灵活基础。数字我都核对了,例子没毛病。学好这些基础工具,啥大数据、小数据,底气都能足!