有没有比for循环更快的方法以有序的方式组合文件



对于某些上下文,我试图将多个名为FILENAME.xxx.xyz(xxx从001开始,增加1(的文件(以有序的方式(组合为一个文件(表示为$COMBINED_file(,然后替换$COMBINDE_file中的多行文本,从另一个文件中获取值(名为$ACTFILE(。我有两个for循环来做这件事,效果非常好。然而,当我有更多的文件时,这个过程往往需要相当长的时间。因此,我想知道是否有人对如何加快这一进程有任何想法?

步骤1:

for i in {001..999}; do
[[ ! -f ${FILENAME}.${i}.xyz ]] && break
cat ${FILENAME}.${i}.xyz >> ${COMBINED_FILE}
mv -f ${FILENAME}.${i}.xyz ${XYZDIR}/${JOB_BASENAME}_${i}.xyz
done

步骤2:

for ((j=0; j<=${NUM_CONF}; j++)); do
let "n = 2 + (${j} * ${LINES_PER_CONF})"
let "m = ${j} + 1"
ENERGY=$(awk -v NUM=$m 'NR==NUM { print $2 }' $ACTFILE)
sed -i "${n}s/.*/${ENERGY}/" ${COMBINED_FILE}
done

我忘了提一下:还有其他名为FILENAME.*.xyz的文件,我不想将其附加到$COMBID_FILE

有关文件的一些详细信息:

FILENAME.xxx.xyz是以下形式的分子xyz文件:第1行:原子数第2行:标题第3行原子数:分子坐标行(原子数+1(:与行1相同行(原子数+2(:标题2…继续(其中第1行至原子数与构象异构体1相关,依此类推(

ACT文件是一个包含能量的文件,其形式为:第1行:conformer1能源第2行:conformer2 Energy2其中former1在第1列,能量在第2列。

目标是使符合者的能量成为组合文件中的标题(其中能量必须是特定符合者的标题(

如果您知道至少存在一个匹配的文件,您应该能够做到这一点:

cat -- ${FILENAME}.[0-9][0-9][0-9].xyz > ${COMBINED_FILE}

请注意,这将与000文件匹配,而您的脚本从001开始计数。如果你知道000不存在,或者如果它存在的话就不是问题,那么你应该能够做到以上几点。

但是,将这些文件移动到另一个目录中的重命名名称中确实需要一个循环,或者一个不太可移植的基于模式的重命名实用程序。

如果你可以更改你的工作流程以保留文件名,它可能只是:

mv -- ${FILENAME}.[0-9][0-9][0-9].xyz ${XYZDIR}/${JOB_BASENAME}

其中,我们现在有一个以作业基本名称命名的目录,而不是路径组件片段。

步骤2的处理应该完全在Awk中实现,而不是shell循环;您可以将文件读取到按行号索引的关联数组中,并对其进行随机访问。

Awk也可以接受多个文件,因此以下模式可能适用于处理单个文件:

awk 'your program' ${FILENAME}.[0-9][0-9][0-9].xyz

例如,就在将它们连接起来并移开之前。那么您就不必依赖于一个固定的LINES_PER_FILE等等。Awk具有FNR变量,该变量是当前文件中的记录;条件/操作对可以判断处理何时转移到下一个文件。

GNU Awk还有扩展名BEGINFILEENDFILE,它们类似于标准BEGINEND,但围绕每个处理过的文件执行;您可以对记录进行一些计算,并在ENDFILE中打印该文件的结果,并为下一个文件清除累积变量。这比检查FNR == 1对最后一个文件执行END操作要好。

如果你真的想在不使用globbing的情况下实现所有文件名,你可以始终使用jotit(在使用科学表示法之前,它就像默认模式下有更多整数位数的seq(:

jot -w 'myFILENAME.%03d' - 0 999 | 
mawk '_<(_+=(NR == +_)*__)' _=17 __=91  # extracting fixed interval
# samples without modulo(%) math

最新更新