1.13 文本处理
一些很多日常操作,其中有典型的两类:
- 从文件里提取你想要的信息
- 修改文件里的内容
当然你可以古法的,一个个 cat 复制,收集或者一个个 vim 修改...
如果你忍受了这种无聊重复的操作,可以试试两个命令:
awksed
1. awk
你可以先把 awk 理解成:
很适合从结构化文本里按列、按模式提取信息。
在计算科研里,一个很常见的场景就是从很多输出文件里批量提取你关心的内容。
例如做一组自旋极化计算后,你可能想从很多个目录里的 OSZICAR 最后一行提取:
E0mag
bash
awk 'END{print $5, $10}' */OSZICAR # 例如从每个 OSZICAR 最后一行提取 E0 和 mag 所在列你可以先这样理解:
END{print}:只在文件最后执行一次$5, $10:取这一行的第 5 列和第 10 列*/OSZICAR:一次处理很多个目录下的OSZICAR
很多时候你最关心的不是前面的每一步,而是最后一步的信息。
如果你不确定 E0 和 mag 在第几列,可以先粗暴一点:
bash
awk 'END{print}' */OSZICAR # 先把每个 OSZICAR 最后一行都打出来这类写法很适合:
- 从很多个结果目录里批量提取最后一步结果
- 快速对比不同结构、不同参数下的
E0和mag - 不想一个个打开
OSZICAR
很多时候,最有用的不是“把整份文件读完”,而是先快速抓出:
- 最后一行
- 某几列数字
所以 awk 的核心价值,可以先理解成:
- 先筛出你关心的行
- 再取你关心的列
2. sed:更适合替换
你可以先把 sed 理解成:
很适合把文本里的某些内容批量替换掉。
在科研里,一个很常见的场景就是做 benchmark 时批量改 INCAR 参数。
例如你想测试一组不同的 ENCUT:
ENCUT = 400ENCUT = 450ENCUT = 500ENCUT = 550
这时你通常会复制出很多个目录,然后在每个目录里把 INCAR 里的 ENCUT 改掉。
最核心的替换命令其实就是:
bash
sed 's/ENCUT = 400/ENCUT = 450/g' INCAR # 把 ENCUT 从 400 换成 450,并输出到屏幕这里最常见的结构是:
bash
sed 's/旧内容/新内容/g' 文件名可以先这样理解:
s= substitute,替换- 第一个
/.../:旧内容 - 第二个
/.../:新内容 g= global,这一行里能替换的都替换
但这里要注意:
bash
sed 's/ENCUT = 400/ENCUT = 450/g' INCAR默认只是把结果打印到终端,不会直接改文件本身。
如果你想直接修改文件,可以用:
bash
sed -i '' 's/ENCUT = 400/ENCUT = 450/g' INCAR # macOS 直接改文件
sed -i 's/ENCUT = 400/ENCUT = 450/g' INCAR # Linux 直接改文件这一点要格外小心,因为一旦用 -i,就是直接改文件了。