iterated mel script from command by command - mel

I am trying to write a mel script that assigns a CV curve (with 5 knots) to each vertex on an animated object. For each vertex on the animated object the base of a single CV curve is then aligned using the constraints in order: geometry, normal (with length of CV curve aligned with normal direction), and point on poly. After this each of the CV curves are made dynamic in the nHair module, with the base anchored to the vertex on the animated object. I have been able to record the mel commands for a single instance of this but do to know how to repeat the same command for all vertices on the animated object
curve -d 3 -p 0 0 0 -p 0 1 0 -p 0 2 0 -p 0 3 0 -p 0 4 0 -p 0 5 0 -k 0 -k 0 -k 0 -k 1 -k 2 -k 3 -k 3 -k 3 ;
select -r pSphere1 ;
select -tgl curve1 ;
geometryConstraint -weight 1;
select -r pSphere1 ;
select -tgl curve1 ;
normalConstraint -weight 1 -aimVector 0 1 0 -upVector 0 1 0 -worldUpType "vector" -worldUpVector 0 1 0;
select -r pSphere1.vtx[184] ;
select -tgl curve1 ;
doCreatePointOnPolyConstraintArgList 2 { "0" ,"0" ,"0" ,"1" ,"" ,"1" ,"0" ,"0" ,"0" ,"0" };
{string $constraint[]=`pointOnPolyConstraint -offset 0 0 0 -weight 1`; setAttr ($constraint[0]+".pSphere1U0") 0.200000; setAttr ($constraint[0]+".pSphere1V0") 0.500000;};
select -r curve1 ;
makeCurvesDynamic 2 { "0", "1", "1", "1", "0"};
select -r follicle1 ;
selectKey -clear ;
setAttr "follicleShape1.pointLock" 1;
(great! can't embed an image yet as I haven't earned enough points...)
I know this is just a screengrab of the normals displayed on a sphere in Maya (if I was allowed to embed it - for now just turn normals display on for a sphere in Maya), but if you can imagine each normal line is actually a CV curve follicle then you can understand what I am trying to script - I want to be able to select all the vertices on the sphere and assign CVs which are then converted to dynamic follicles...

Related

Nurbs curve parameters in Maya?

I get a Maya .ma file, I want to understand the parameters for nurbsCurve, the file has contents like this:
createNode nurbsCurve; # create a nurbsCurve
setAttr -k off ".v"; # set attribute about knots?
setAttr ".cc" -type "nurbsCurve" # attribute setting
3 1 0 no 3
6 0 0 0 1 1 1
4 # 4 stand for the below has 4 coordiniates
7.82436 0.545707 8.54539
7.86896 0.545707 9.61357
7.28368 0.53563 9.8433
6.06638 0.53563 9.89412
;
...
I don't understand what the line 3 1 0 no 3 and 6 0 0 0 1 1 1 stands for, anybody understand what these lines stand for?
Here's what I know so far, only the first three figures.
[3] [1] [0]
corresponds to:
[degree] [span] [index of the form: open/closed/periodic]

How to use offset in arrays in bash?

Here is my code.
#! /bin/bash
array=(3 2 1 0 0 0 0 0 0 0)
for i in {0..10}
do
this=${array:$i:$((i+1))}
echo $this
done
I want to print each number of my number separately. I have used this line to get the array elements using an offset number.
this=${array:$i:$((i+1))}
However I am only getting 3 printed and rest all are new lines. I basically want to print 3, 2, 1 etc on separate lines. How do I correct this?
First, you need to use the whole array array[#], not array.
echo "${array[#]:3:2}"
Then, you may change the index to simple variable names:
this=${array[#]:i:i+1}
And then, you probably need to extract just one value of the list:
this=${array[#]:i:1}
Try this code:
array=(3 2 1 0 0 0 0 0 0 0)
for i in {0..10}
do
this=${array[#]:i:1}
echo "$this"
done
There is no reason to use an array slice here, just access the individual elements of the array. Try this:
#! /bin/bash
array=(3 2 1 0 0 0 0 0 0 0)
for i in {0..10}
do
this=${array[$((i+1))]}
echo $this
done
In general you can access a single element of an array like that: ${array[3]}.
Note that in this case, it would have been preferable to do this:
array=(3 2 1 0 0 0 0 0 0 0)
for this in "${array[#]}"
do
echo $this
done

Filter column from file based on header matching a regex

I have the following file
foo_foo bar_blop baz_N toto_N lorem_blop
1 1 0 0 1
1 1 0 0 1
And I'd like to remove the columns with the _N tag on header (or selecting all the others)
So the output should be
foo_foo bar_blop lorem_blop
1 1 1
1 1 1
I found some answers but none were doing this exactly
I know awk can do this but I don't understand how to do it by myself (I'm not good at awk) with this language.
Thanks for the help :)
awk 'NR==1{for(i=1;i<=NF;i++)if(!($i~/_N$/)){a[i]=1;m=i}}
{for(i=1;i<=NF;i++)if(a[i])printf "%s%s",$i,(i==m?RS:FS)}' f|column -t
outputs:
foo_foo bar_blop lorem_blop
1 1 1
1 1 1
$ cat tst.awk
NR==1 {
for (i=1;i<=NF;i++) {
if ( (tgt == "") || ($i !~ tgt) ) {
f[++nf] = i
}
}
}
{
for (i=1; i<=nf; i++) {
printf "%s%s", $(f[i]), (i<nf?OFS:ORS)
}
}
$ awk -v tgt="_N" -f tst.awk file | column -t
foo_foo bar_blop lorem_blop
1 1 1
1 1 1
$ awk -f tst.awk file | column -t
foo_foo bar_blop baz_N toto_N lorem_blop
1 1 0 0 1
1 1 0 0 1
$ awk -v tgt="blop" -f tst.awk file | column -t
foo_foo baz_N toto_N
1 0 0
1 0 0
The main difference between this and #Kent's solution is performance and the impact will vary based on the percentage of fields you want to print on each line.
The above when reading the first line of the file creates an array of the field numbers to print and then for every line of the input file it just prints those fields in a loop. So if you wanted to print 3 out of 100 fields then this script would just loop through 3 iterations/fields on each input line.
#Kent's solution also creates an array of the field numbers to print but then for every line of the input file it visits every field to test if it's in that array before printing or not. So if you wanted to print 3 out of 100 fields then #Kent's script would loop through all 100 iterations/fields on each input line.

substituting some elements of a matrix with new values bash

I am trying to read in a file, change some parts of it and write it to a new file in bash. I know that I can substitute the parts with the "sed" command but I do not know how to it in my case which is a matrix in the beginning of my file. Here is how my file looks like
alpha
1 0 0
0 1 0
0 0 1
some text here
more numbers here
and I am trying to substitute the values of the matrix above in a for loop like
for i in 1 2 3 4
do
replace 1 0 0
0 1 0
0 0 1
by 1*(1+${i}) ${i}/2 0
${i}/2 1 0
0 0 1
and print the whole file with the substitution to newfile.${i}
done
I want to do this in bash. Any idea how to do this? And I only want to change this part and only this part!
Awk is more suitable for this:
for i in {1..4}; do awk -v i="$i" -f substitute.awk oldfile.txt > newfile.$i; done
using the following substitute.awk script:
{
if( NR == 3 ) { print 1 + i, i / 2, 0 }
else if( NR == 4 ) { print i / 2, 1, 0 }
else print $0
}
(assuming, as you wrote, that the matrix is always in lines 3 through 5; in your example it is in lines 2 through 4)

Array disappear in bash script

I'm writing a script to collect some various network statistics.
What I'm trying to do is to produce some delta data from the netstat -i command.
I'm collecting the needed data with the following bash code:
declare -a array
n=0
netstat -i | tail -n +3 | while read LINE; do
echo "Setting array[$n] to $LINE"
array[$n]=$LINE
echo "array now have ${#array[#]} entries"
let n=$n+1
done
echo "array now have ${#array[#]} entries"
output from this command is:
Setting array[0] to eth0 1500 0 4946794 0 0 0 2522971 0 0 0 BMRU
array now have 1 entries
Setting array[1] to lo 16436 0 25059 0 0 0 25059 0 0 0 LRU
array now have 2 entries
Setting array[2] to vmnet1 1500 0 6 0 0 0 1126 0 0 0 BMRU
array now have 3 entries
Setting array[3] to vmnet8 1500 0 955 0 0 0 1054 0 0 0 BMRU
array now have 4 entries
Setting array[4] to wlan0 1500 0 613879 0 0 0 351194 0 0 0 BMU
array now have 5 entries
array now have 0 entries
As you can see, the array actually disappear after the while loop, and I do not understand why.
Any time you use a pipe you create an implicit subshell. When that subshell terminates, so do its variables. A quick fix for this is to not pipe stuff to read. You can accomplish the above using process substitution:
while read LINE; do
echo "Setting array[$n] to $LINE"
array[$n]=$LINE
echo "array now have ${#array[#]} entries"
let n=$n+1
done < <(netstat -i | tail -n +3)
A more POSIX compliant approach (read: more portable, less bashist) is to make everything happen in the subshell:
netstat -i | tail -n +3 | {
declare -a array
n=0
while read LINE; do
echo "Setting array[$n] to $LINE"
array[$n]=$LINE
echo "array now have ${#array[#]} entries"
let n=$n+1
done
echo "array now have ${#array[#]} entries"
}
You can read the fine points of this (and more) at Greg Wooledge's wiki.
If your only goal is to put the output of a command into an array (linewise), you'd better use the (sadly not very well-known) mapfile bash builtin, it's by far the most efficient (and the best suited for code golf, count how many character strokes I have compared to the other possibilities):
mapfile -t array < <(netstat -i | tail -n +3)
The other answers explain why your construct didn't work (pipe is in a subshell and all that).
help mapfile for all the details and possibilities of that command.
Ok, are you ready?
There is how to transform netstat -i | tail -n +3 in a bash Associative Array of array:
declare -A AANET
while read -a line ;do
declare -a AI$line
eval "AI$line=(${line[#]})"
AANET[$line]=AI$line
done < <(
netstat -i |
tail -n +3)
Than now:
echo ${!AANET[#]}
venet0 eth1 eth0 lo br0
echo ${AANET[eth0]}
AIeth0
And for sub-associative, we have to use eval:
eval echo \${${AANET[eth0]}[#]}
eth0 1500 0 17647 0 0 0 35426 0 0 0 BMPU
eval echo \${${AANET[eth0]}[1]}
1500
eval echo \${${AANET[eth0]}[3]}
17647
eval echo \${${AANET[eth0]}[7]}
35426
eval echo \${${AANET[eth0]}[#]:3:5}
17647 0 0 0 35426
An for assing a temporary variable:
eval currentBin=\${${AANET[eth0]}[3]} currentBout=\${${AANET[eth0]}[7]}
echo $currentBout
35426
echo $currentBin
17647
or even too:
eval "declare -a currentVals=(\${${AANET[eth0]}[#]:3:8})"
echo ${currentVals[0]}
17647
echo ${currentVals[4]}
35426
echo ${currentVals[#]}
17647 0 0 0 35426 0 0 0
Edit:
Ok, if it is possible without eval!
for aKey in ${!AANET[#]};do
fields=(${AANET[$aKey]}{[1],[3],[7]});
echo $aKey ${!fields} ${!fields[1]} ${!fields[2]}
done |
xargs printf "%-9s %12s %12s %12s\n" IFace MTU RX TX
IFace MTU RX TX
venet0 1500 0 0
eth1 1500 6400292 6942577
eth0 1500 17647 35426
lo 16436 83 83
Don't pipe to a loop, bash substitutes variables first and then starts a subshell without access to your array.
Do it like this. Nice and simple.
array=()
for alias in `netstat -i | tail -n +3`; do
array+=($alias)
done
echo ${array[#]}

Resources