如何将Shell变量传递给grep的-A参数提取SDF文件原子坐标
解决grep -A参数传递Shell变量的问题
核心解决方案
你之前的命令出错主要有两个原因:一是缺少要匹配的目标模式(V2000),导致grep等待标准输入;二是部分写法对参数格式处理错误。正确的命令应该是:
grep -A "$no_atoms" "V2000" *.sdf
或者当变量值为纯数字时,无引号的写法也安全:
grep -A $no_atoms V2000 *.sdf
这样就能匹配到包含V2000的行,并输出该行之后的$no_atoms行(即所有原子坐标)。
为什么之前的写法失败?
grep -A{$no_atoms} *.sdf:-A参数不需要额外的花括号,grep会把{42}当成一个非法的长度参数。grep -A\$no_atoms *.sdf:转义$导致变量未被解析,grep直接把$no_atoms当成无效的长度值。grep -A"$no_atoms" *.sdf:未指定匹配模式,grep进入等待标准输入的状态,因此会出现光标卡住的情况。
优化:处理多个SDF文件的场景
如果目录下有多个SDF文件(每个文件原子数不同),直接用grep V2000 *.sdf | awk '{print $1}'会把所有文件的原子数合并到一个变量中,传递给grep -A会出错。可以用循环逐个处理:
for file in *.sdf; do no_atoms=$(grep "V2000" "$file" | awk '{print $1}') grep -A "$no_atoms" "V2000" "$file" done
每个文件会单独提取对应的原子数,并输出正确的坐标行。
额外技巧:用awk一步完成提取
不需要grep+变量传递,直接用awk就能高效完成原子数读取和坐标提取:
awk '/V2000/{n=$1; print; for(i=0;i<n;i++){getline; print}}' *.sdf
这个命令的逻辑:
- 匹配到含
V2000的行时,记录第一个字段(原子数n) - 打印该行,然后循环读取并打印接下来的n行(原子坐标)
内容的提问来源于stack exchange,提问作者blakem
相关产品推荐
相关产品推荐

