Filtering output of permutations using bash
I am really a Newbie in bash programing and I need to perform a permutation, which I did using one post from this forum as follow Generating permutations using bash.
#!/bin/bash
list=`echo {1..12}`
for c1 in $list
do
for c2 in $list
do
for c3 in $list
do
开发者_运维百科 echo $c1-$c2-$c3
done
done
done
The output is
1-1-1
1-1-2
1-1-3 ...
but I do not want to have a number repeated in the line (1-1-1). Meaning if the number 1 is in the first position, I do not want it neither in the second nor in the third. like this
1-2-3
1-2-4
1-2-5
...
Can anybody help me? any hint is welcome.
I think you need to change your echo line to:
[ $c1 -ne $c2 -a $c1 -ne $c3 -a $c2 -ne $c3 ] && echo $c1-$c2-$c3
The link at the top of your question already includes a nice answer on how to do permutations in bash. But I think that's not the answer you're looking for so I suggest you to use the following script:
#!/bin/bash
list=`echo {1..12}`
for c1 in $list
do
for c2 in $list
do
if [ "$c1" != "$c2" ]; then
for c3 in $list
do
if [ "$c1" != "$c3" ]; then
echo $c1-$c2-$c3
fi
done
fi
done
done
Does this do what you're looking for?
#!/bin/bash
list=$(echo {1..12})
for c1 in $list
do
for c2 in $list
do
if (( c2 != c1 ))
then
for c3 in $list
do
if (( c3 != c2 && c3 != c1))
then
echo $c1-$c2-$c3
fi
done
fi
done
done
Partial output:
1-2-3
1-2-4
1-2-5
1-2-6
1-2-7
1-2-8
1-2-9
1-2-10
1-2-11
1-2-12
1-3-2
1-3-4
...
12-10-8
12-10-9
12-10-11
12-11-1
12-11-2
12-11-3
12-11-4
12-11-5
12-11-6
12-11-7
12-11-8
12-11-9
12-11-10
The solution in the questions gives a Cartesian product. The following function generates the permutations of a set of values.
declare -a set=( 1 2 3 ) # set to permute
declare -i n=${#set[@]}
permute ()
{
declare -i k=$1
declare -i i
declare -i save
if [ $k -lt $((n-1)) ] ; then
for (( i=k; i<n; i+=1 )); do
save=${set[k]} # exchange elements
set[k]=${set[i]}
set[i]=$save
permute $((k+1)) # recurse
save=${set[k]} # exchange elements
set[k]=${set[i]}
set[i]=$save
done
else
(IFS='-'; echo -e "${set[*]}")
fi
} # ---------- end of function permute ----------
permute 0
The output:
1-2-3
1-3-2
2-1-3
2-3-1
3-2-1
3-1-2
I was having a similar problem but with text characters, so, just in case it may help:
for i in {a..z} ; do for b in {a..z} ; do [[ ! "$i" == "$b" ]] && echo -e "$i $b" | xargs -n 1 | sort | xargs ; done ; done | sort -u
It will permutate a to z with a to z, not only not repeating characters, "a a", but also without redundancies such as "ab" and "ba", echoing just "ab", thanks to the "inline sorting" of elements (xargs | sort | xargs) followed by the final "sort -u" (or "uniq").
精彩评论