Nested loop with two arrays
I have two sets of arrays with a variable number of elements, for instance:
chain=(B C)
hresname=(BMA MAN NAG NDG)
I am parsing a number of files that may contain element开发者_运维问答s from the array chain at a given position and elements of the array hresname at a different position (position is always fixed in both cases). This is a sample of the data:
ATOM 5792 CB MET D 213 49.385 -5.683 125.489 1.00142.66 C
ATOM 5793 CG MET D 213 50.834 -5.674 125.990 1.00154.50 C
ATOM 5794 SD MET D 213 51.530 -7.337 126.277 1.00164.73 S
ATOM 5795 CE MET D 213 52.854 -7.386 125.068 1.00169.73 C
HETATM 5797 C1 NAG B 323 70.090 50.934 125.869 1.00 86.35 C
HETATM 5798 C2 NAG B 323 69.687 52.074 126.879 1.00 95.95 C
HETATM 5799 C3 NAG B 323 68.377 52.740 126.390 1.00 87.65 C
HETATM 5800 C4 NAG B 323 68.598 53.314 125.014 1.00 83.97 C
First I need to copy lines starting with ATOM whose 5th column matches each of the elements of the array chain to separate files:
while read pdb ; do
for c in "${chain[@]}" ; do
#if [ ${#chain[@]} -eq 1 ] && \
if [ $(echo "$pdb" | cut -c1-4) == "ATOM" ] && \
[ $(echo "$pdb" | cut -c22-23) == "${chain[$c]}" ]; then
echo "$pdb" >> ../../properpdb/${pdbid}_${chain[$c]}.pdb
fi
done
done < ${pdbid}.pdb
This works well (slow but sure). Both the commented and the uncommented versions work.
Next I want to copy lines that start with HETATM and whose 4th column matches elements of the hresname but only if those lines also match an element form the chain array at cloumn number 5th:
while read pdb ; do
for c in "${chain[@]}" ; do
for h in "${hresname[@]}" ; do
if [ ${#chain[@]} -eq 1 ] && \
[ $(echo "$pdb" | cut -c1-6) == "HETATM" ] && \
[ $(echo "$pdb" | cut -c22-23) == "${chain[$c]}" ] \
[ $(echo "$pdb" | cut -c18-20) == "${hresname[$h]}" ] ; then
echo "$pdb" >> ../../properpdb/${pdbid}_${chain[$c]}.pdb
fi
done
done
done < ${pdbid}.pdb
However, this does not work. I repeatedly receive an error:
line 66: [: too many arguments
Line 66 is:
[ $(echo "$pdb" | cut -c22-23) == "${chain[$c]}" ] \
Which puzzles me because the error happens even if I restrict the loop to chain arrays containing a single element.
According to other StackOverflow questions, it should be perfectly possible to do this in bash. Any idea what the problem could be?
You for get to add &&
, change this line:
[ $(echo "$pdb" | cut -c22-23) == "${chain[$c]}" ] \
To
[ $(echo "$pdb" | cut -c22-23) == "${chain[$c]}" ] &&\
Update: You have too many errors in the script, I fixed it and it's now working. I suggest you read the for loop syntax in the bash manual first.
chain=(B C)
hresname=(BMA MAN NAG NDG)
while read pdb ; do
for c in ${chain[@]} ; do
for h in ${hresname[@]} ; do
if [ $(echo "$pdb" | cut -c1-6) == "HETATM" ] && \
[ $(echo "$pdb" | cut -c22-23) == "$c" ] && \
[ $(echo "$pdb" | cut -c18-20) == "$h" ] ; then
echo "$pdb" >> ../../properpdb/${pdbid}_${chain[$c]}.pdb
fi
done
done
done
精彩评论