我想连接两个或多个文件,具体取决于名称是否包含数组中的元素。
我正在逐行阅读这种文件(proteome.pisa):
2PJY_p chain=(B C) hresname=() hresnumber=() hatom=() model=() altconf=()
2Q7N_p chain=(A E F G H I J K L) hresname=(FUC MAN NAG) hresnumber=() hatom=() model=() altconf=()
对于每一行,脚本在第一列上提取字符串并将其定义为变量pdbid。然后它接受第二列并将其定义为数组(元素链$ c)。然后它检查是否存在名为$ {pdbid} _ $ {c} _p.pdb的文件,如果存在,则将其内容合并到文件$ {pdbid} _p _ $ {chains} .pdb
这是剧本:
while read line ; do
echo "$line" > pdb.line
cut -f1 pdb.line > pdb.list
sed -i 's/.*/\"&\"/' pdb.list
sed -i 's/_p//g' pdb.list
awk '{ printf "pdbid="; print }' pdb.list > pdbid.list
cut -f2 pdb.line > chain.list
source pdbid.list
source chain.list
chains=`printf "%s" "${chain[@]}"`
for c in ${chain[@]} ; do
if [ ${#chain[@]} -gt 1 ] && \
[ -f ${pdbid}_${c}_p.pdb ] ; then
cat ${pdbid}_${chain[$c]}_p.pdb >> ${pdbid}_p_${chains}.pdb
fi
done
done < proteome.pisa
预期的行为是合并,例如,第一行,2PJY_p_B.pdb和2PJY_p_C.pdb,名为2PJY_p_BC.pdb。然而,它实际上做的是合并第一个文件两次。我不明白为什么......
答案 0 :(得分:1)
这是一个很好的问题,因为它证明了bash不能单独完成所有事情。相反,它需要帮助程序,如awk,cut,......我查看了你的解决方案,看起来在两个源行之后,你希望设置变量pdbid,chain和chain。但是,您的脚本没有正确设置它们,我可以帮助完成该部分。我不太了解Perl,但认为Perl在这种情况下会很好用。这是 makevars.pl :
while (<STDIN>) {
my($line) = $_;
if ($line =~ /^(.*)_p.*chain=\((.*)\).*hresname.*$/) {
print "pdbid=$1\n";
print "chain=($2)\n";
$chains = $2;
$chains =~ s/ //g;
print "chains=$chains\n";
}
}
这是shell脚本:
while read line
do
echo "$line" | perl makevars.pl >setvars.sh
source setvars.sh
# Now, pdbid, chain, and chains are set, do your things
done < proteome.pisa
我希望这会有所帮助。
答案 1 :(得分:1)
我建议使用sed
将输入预处理为更简单的形式,然后循环。这假设chain=(...)
始终是一行上的第一个这样的属性。
#!/bin/sh
# Replace 2ICQ_p chain=(A B C ... Z) attribs= ... with
# 2ICQ_p A B C ... Z
sed 's/ chain=\(//;s/\).*//' <proteome.pisa |
while read pdbid chain; do
chains=${chain/ /}
for c in $chain; do
test -e ${pdbid}_${c}_p.pdb || continue
cat ${pdbdid}_${c}_p.pdb
done >${pdbid}_p_${chains}.pdb
done
这可以避免使用临时文件,这些文件会破坏你的第一个脚本;采购生成的文件看起来也很惊人,如果不是惊人的话(通常你可以使用反引号来做这类事情,但这里并不是真的需要它们。)
sed
有多种变种;一些(例如Linux)想要一个字面括号被反斜杠,而另一些(例如Mac OSX)则不需要。如果这不起作用,请尝试取出反斜杠。
read
将输入拆分为空格,以便第一个变量名称接收第一个标记等;最后一个命名变量接收剩下的任何内容,而不需要额外的空格分割。 continue
跳转到封闭的for
或while
循环的下一次迭代。除此之外,这应该是相当不言自明的。如果你真的很想在纯Bourne shell中完成所有操作,那么开头的sed
替换可能会被涉及字符串替换的东西替换。
答案 2 :(得分:0)
问题似乎是这一行中数组的定义:
cat ${pdbid}_${chain[$c]}_p.pdb >> ${pdbid}_p_${chains}.pdb
将其更改为:
cat ${pdbid}_${c}_p.pdb >> ${pdbid}_p_${chains}.pdb
似乎可以解决问题。
此外,我已经双重引用了所有“$ {chain [@]}”。