Bash中对固定行结构的分子系综样本实现随机抽样
纯Bash实现固定结构分子系综文件随机抽样
已知文件结构为每22行对应1个完整样本:第1行是值为20的原子数、第2行是体系能量、第3-22行共20行是原子三维坐标,全程仅用Bash及GNU coreutils自带工具即可完成无偏随机抽样,不需要依赖Python等外部解释器。
核心思路
因为每个样本块长度完全固定,不需要逐行匹配分隔符,直接按固定行块切割即可:
- 统计文件总行数,除以单样本22行得到总样本量
- 生成指定数量的不重复随机整数,对应要抽取的样本块序号
- 按序号计算每个样本块的起止行号,直接提取对应行段,保证每个样本的22行结构完整
可直接复用的实现脚本
#!/bin/bash # 入参1:分子系综源文件路径 # 入参2:需要随机抽取的样本数量 INPUT_FILE="$1" DRAW_CNT="$2" SINGLE_BLOCK_LINES=22 # 单个样本固定占22行 # 入参校验 if [ $# -ne 2 ]; then echo "调用方式: $0 <系综文件路径> <抽取样本数>" >&2 exit 1 fi if [ ! -r "$INPUT_FILE" ]; then echo "错误:文件 $INPUT_FILE 不存在或无读权限" >&2 exit 1 fi # 统计总样本数,自动跳过末尾不足22行的残缺块 TOTAL_LINES=$(wc -l < "$INPUT_FILE") TOTAL_SAMPLES=$(( TOTAL_LINES / SINGLE_BLOCK_LINES )) if [ "$DRAW_CNT" -gt "$TOTAL_SAMPLES" ]; then echo "错误:抽取数量$DRAW_CNT超过总有效样本数$TOTAL_SAMPLES" >&2 exit 1 fi # 生成不重复随机块号,按序号排序后逐块提取 shuf -i 1-"$TOTAL_SAMPLES" -n "$DRAW_CNT" | sort -n | while read -r block_num; do start=$(( (block_num - 1) * SINGLE_BLOCK_LINES + 1 )) end=$(( block_num * SINGLE_BLOCK_LINES )) sed -n "${start},${end}p" "$INPUT_FILE" done
使用方式
- 将上述代码保存为
mol_sample.sh,执行chmod +x mol_sample.sh添加执行权限 - 以从100个样本的
ensemble.xyz中抽取4个样本、结果保存到sample_4.xyz为例,执行命令:./mol_sample.sh ensemble.xyz 4 > sample_4.xyz
补充说明
- 所有用到的
wc/shuf/sed都是Linux环境默认自带的工具,macOS环境安装coreutils后即可正常使用,没有额外依赖,完全适配现有Bash数据处理流程 - 按固定块切割的方式执行效率极高,哪怕是十万级样本量的大文件也能快速处理,不会出现逐行遍历的性能问题
- 提取过程严格保留每个样本的完整22行结构,不会出现表头和坐标错位、行缺失的问题
- 如果需要固定抽样结果可复现,给
shuf添加参数--random-source=<(echo 你的固定种子字符串)即可
内容的提问来源于stack exchange,提问作者saya
相关产品推荐
相关产品推荐

