不同列表中的元素匹配

时间:2015-02-09 15:49:36

标签: bash list

通常:)我有两组具有相同名称但扩展名不同的输入文件。

使用bash我创建了一个简单的脚本,它创建了2个具有相同元素名称的列表,同时从2个目录中循环了2组文件,并且只使用名称没有扩展名作为这些列表的元素:

#!/bin/bash
workdir=/data2/Gleb/TEST/claire+7d4+md/water_analysis/MD1
traj_all=${workdir}/tr_all
top_all=${workdir}/top_all

#make 2 lists for both file types
Trajectories=('');
Topologies=('');

#looping of 1st input files
echo "Trr has been found in  ${traj_all}:"
for tr in ${traj_all}/*; do # ????
 tr_n_full=$(basename "${tr}")
 tr_n="${tr_n_full%.*}"
 Trajectories=("${Trajectories[@]}" "${tr_n}");
done
#sort elements within ${Trajectories[@]} lists!!  >> HERE I NEED HELP!

#looping of 2nd files
echo "Top has been found in ${top_all}:"
for top in ${top_all}/*; do # ????
 top_n_full=$(basename "${top}")
 top_n="${top_n_full%.*}"
 Topologies=("${Topologies[@]}" "${top_n}");
done
#sort elements within ${Topologies[@] lists!!  >> HERE I NEED HELP!


#make input.in file for some program- matching of elements from both lists  >> HERE I NEED HELP!
for i in $(seq 1 ${#Topologies[@]}); do
printf "parm $top_all/${Topologies[i]}.top \ntrajin $traj_all/${Trajectories[i]}.mdcrd\nwatershell ${Area} ${output}/watershell_${Topologies[i]}_${Area}.dat > output.in
done

如果有人为我提供了改进此脚本的可能性,我会感激不尽: 1)我需要在每个列表中添加最后一个元素后,以相似的模式对两个列表中的元素进行排序; 2)我需要在脚本的最后一步添加一些测试,它将创建最终的output.in文件,以防两个列表中的元素相同(原则上在这种情况下它总是应该是相同的!)在此操作期间由printf匹配。

感谢您的帮助,

格列勃

1 个答案:

答案 0 :(得分:0)

这是创建数组的一种更简单的方法:

# Create an empty array
Trajectories=();

for tr in "${traj_all}"/*; do
  # Remove the string of directories
  tr_base=${tr##*/}
  # Append the name without extension to the array
  Trajectories+="${tr_base%.*}"
done

在bash中,这通常会产生一个排序列表,因为glob中*的扩展是有序的。但您可以使用sort对其进行排序;如果您确定文件名中没有换行符,则最简单:

mapfile -t sorted_traj < <(printf %s\\n "${Trajectories[@]}" | sort)

要比较两个已排序的数组,您可以使用join

# convenience function; could have helped above, too.
lines() { printf %s\\n "$@"; }
# Some examples:
# 1. compare a with b and print the lines which are only in a
join -v 1 -t '' <(lines "${a[@]}") <(lines "${b[@]}")
# 2. create c as an array with the lines which are only in b
mapfile -t c < <( join -v 2 -t '' <(lines "${a[@]}") <(lines "${b[@]}") )

如果您创建两个差异列表,那么如果两个列表都为空,则两个数组相等。但是,如果你期望两个数组都是相同的,如果这是时间关键的(可能不是),你可以做一个简单的预检:

if [[ "${a[*]}" = "${b[*]}" ]]; then
  # the arrays are the same
else
  # the arrays differ; do some more work to see how.
fi