mel2pyStr fails when selecting group of objects - maya

I am trying to convert a bunch of MEL code into Python in Maya 2015 like this:
mel2py.mel2pyStr(melCmd,pymelNamespace='pm', verbosity=4, forceCompatibility=True)
where melCmd is a multi-line code.
But it fails when converting the following line:
select -add pPipe1.e[2500:2549] ;
The error states that : is unexpected:
p_expression - line 12
original token:
['None', '2500']
result:
2500
# Result : <Token # 0x18faa7a2678> ('2500')
#
# State : 271
# Stack : translation_unit ID command_statement_input_list ID LBRACKET expression . LexToken(COLON,u':',12,407)
# ERROR: Error : translation_unit ID command_statement_input_list ID LBRACKET expression . LexToken(COLON,u':',12,407)
#
# State : 0
# Stack : . $end
# ERROR: Error : . $end
# Error: MelParseError: file C:\Program Files\Autodesk\Maya2015\Python\lib\site-packages\pymel\tools\mel2py\melparse.py line 2940: Errors:
line 12 (COLON): : #
I am trying to select (and then modify) several edges at once. How should I do it in Python? Why does mel2py fail?
Any suggestions are welcome.
Here is the full MEL code:
CreatePolygonPipe;
setToolTo CreatePolyPipeCtx;
setAttr "polyPipe1.thickness" 0.6;
polyPipe -ch on -o on -r 4.343087 -h 4.057391 -t 0.6 ;
// Result: pPipe1 polyPipe1 //
select -addFirst polyPipe1 ;
setAttr "polyPipe1.subdivisionsAxis" 50;
setAttr "polyPipe1.subdivisionsHeight" 37.4;
setAttr "polyPipe1.subdivisionsHeight" 50;
select -r pPipe1.e[2546] ;
select -r pPipe1.e[2546] ;
select -add pPipe1.e[2500:2549] ;
select -tgl pPipe1.e[10] ;
select -add pPipe1.e[0:49] ;
ScaleToolWithSnapMarkingMenu;
dR_ScaleToolMarkingMenuPopDown;
scale -r -p -4.723702cm 1.014348cm -1.380022cm 1.054283 1.054283 1.054283 ;
select -r pPipe1.e[2498] ;
select -add pPipe1.e[2450:2499] ;
select -tgl pPipe1.e[61] ;
select -add pPipe1.e[50:99] ;
scale -r -p -4.723702cm 1.014348cm -1.380022cm 1.025089 1.025089 1.025089 ;
select -r pPipe1.e[2556] ;
select -add pPipe1.e[2550:2599] ;
select -tgl pPipe1.e[5096] ;
select -add pPipe1.e[5050:5099] ;
scale -r -p -4.723702cm 1.014348cm -1.380022cm 0.960232 0.960232 0.960232 ;
select -r pPipe1.e[2644] ;
select -add pPipe1.e[2600:2649] ;
select -tgl pPipe1.e[5044] ;
select -add pPipe1.e[5000:5049] ;
scale -r -p -4.723702cm 1.014348cm -1.380022cm 0.981905 0.981905 0.981905 ;
select -r pPipe1.e[2546] ;
select -add pPipe1.e[2500:2549] ;
TranslateToolWithSnapMarkingMenu;
dR_TranslateToolMarkingMenuPopDown;
move -r 0 -0.07989 0 ;
select -r pPipe1.e[46] ;
select -add pPipe1.e[0:49] ;
move -r 0 0.07989 0 ;
select -d pPipe1.e[0:49] ;
select -r pPipe1 ;
select -cl ;

Basically its crashing on string and I am not if this is a expected behavior, this is how you can fix it
melCmd = 'select -add "pPipe1.e[2500:2549]";'

Related

diff two arrays each containing files paths into a third array (for removal)

In the function below you will see notes on several attempts to solve this problem; each attempt has a note indicating what went wrong. Between my attempts there is a line from another question here which purports to solve some element of the matter. Again, I've added a note indicating what that is supposed to solve. My brain is mush at this point. What is the stupid simple thing I've overlooking?
function func_removeDestinationOrphans() {
readarray -d '' A_Destination_orphans < <( find "${directory_PMPRoot_destination}" -type f -print0 )
for (( i = 0 ; i < ${#A_Destination_orphans[#]} ; i++ )) ; do
printf '%s\n' "→ ${A_Destination_orphans[${i}]}" # path to each track
done
printf '%b\n' ""
# https://stackoverflow.com/questions/2312762/compare-difference-of-two-arrays-in-bash
# echo ${Array1[#]} ${Array2[#]} | tr ' ' '\n' | sort | uniq -u ## original
# Array3=(`echo ${Array1[#]} ${Array2[#]} | tr ' ' '\n' | sort | uniq -u `) ## store in array
# A_Destination_orphans_diff=(`echo "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" | tr ' ' '\n' | sort | uniq -u `) # drops file path after space
# printf "%s\0" "${Array1[#]}" "${Array2[#]}" | sort -z | uniq -zu ## newlines and white spaces
# A_Destination_orphans_diff=($( printf "%s\0" "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" | sort -z | uniq -zu )) # throws warning and breaks at space but not newline
# printf '%s\n' "${Array1[#]}" "${Array2[#]}" | sort | uniq -u ## manage spaces
# A_Destination_orphans_diff=($( printf '%s\n' "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" | sort | uniq -u )) # breaks at space and newline
# A_Destination_orphans_diff="($( printf '%s\n' "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" | sort | uniq -u ))" # creates string surrounded by ()
# A_Destination_orphans_diff=("$( printf '%s\n' "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" | sort | uniq -u )") # creates string
# A_Destination_orphans_diff=($( printf '%s\n' ${A_Destination_dubUnders[#]} ${A_Destination_orphans[#]} | sort | uniq -u )) # drops file path after space
for (( i = 0 ; i < ${#A_Destination_orphans_diff[#]} ; i++ )) ; do
printf '%s\n' "→ ${A_Destination_orphans_diff[${i}]}" # path to each track
done
printf '%b\n' ""
for (( i = 0 ; i < ${#A_Destination_orphans_diff[#]} ; i++ )) ; do
echo # rm "${A_Destination_orphans_diff[i]}"
done
func_EnterToContinue
}
This throws warning and breaks at space but not newline because you build the array with direct assignment of syntax construct. When an entry contains spaces, it also splits break to a new entry.
A_Destination_orphans_diff=($( printf "%s\0" "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" | sort -z | uniq -zu ))
To avoid the issue of the method above, you can mapfile/readarray a null delimited entries stream.
mapfile -t -d '' A_Destination_orphans_diff < <(
printf "%s\0" "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" |
sort -z |
uniq -zu
)
In case your shell version is too old to support mapfile you can perform the same task with IFS=$'\37' read -r -d '' -a array.
$'\37' is shell's C-Style string syntax with octal code 37, which is ASCII 31 US for Unit Separator:
IFS=$'\37' read -r -d '' -a A_Destination_orphans_diff < <(
printf "%s\0" "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" |
sort -z |
uniq -zu |
xargs -0 printf '%s\37'
)
To remove all files not present in A_Destination_dubUnders array you could:
func_removeDestinationOrphans() {
find "${directory_PMPRoot_destination}" -type f -print0 |
sort -z |
join -z -v1 -t '' - <(printf "%s\0" "${A_Destination_dubUnders[#]}" | sort -z) |
xargs -0 echo rm
}
Use join or comm to find elements not present in one list and present in another list. I am usually wrong about -v1, so try with -v2 if it echoes the elements from wrong list (I do not understand if you want to remove files present in A_Destination_dubUnders list or not present, you did not specify that).
Note that function name() is a mix of ksh and posix function definition. Just name() {. See bash hackers wiki obsolete
Here is the working version with modifications thanks to suggested input from the first two respondents (thanks!).
function func_removeDestinationOrphans() {
printf '%s\n' " → Purge playlist orphans: " ""
printf '%b\n' "First we will remove any files not present in your proposed playlist. "
func_EnterToContinue
bash_version="$( bash --version | head -n1 | cut -d " " -f4 | cut -d "(" -f1 )"
if printf '%s\n' "4.4.0" "${bash_version}" | sort -V -C ; then
readarray -d '' A_Destination_orphans < <( find "${directory_PMPRoot_destination}" -type f -print0 ) # readarray or mapfile -d fails before bash 4.4.0
readarray -t -d '' A_Destination_orphans_diff < <(
printf "%s\0" "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" |
sort -z |
uniq -zu
)
else
while IFS= read -r -d $'\0'; do
A_Destination_orphans+=( "$REPLY" )
done < <( find "${directory_PMPRoot_destination}" -type f -print0 )
IFS=$'\37' read -r -d '' -a A_Destination_orphans_diff < <(
printf "%s\0" "${A_Destination_dubUnders[#]}" "${A_Destination_dubUnders[#]}" "${A_Destination_orphans[#]}" |
sort -z |
uniq -zu |
xargs -0 printf '%s\37'
)
fi
if [[ ! "${A_Destination_orphans_diff[*]}" = '' ]] ; then
for (( i = 0 ; i < ${#A_Destination_orphans_diff[#]} ; i++ )) ; do
rm "${A_Destination_orphans_diff[i]}"
done
fi
}
If you would like to see the entire Personal Music Player sync script, you can find that via my GitHub.

How to speed up bash random name generation?

i have problem with my code performance. It is running very slow. I need to generate million+ random persons for my postgres db and insert them into db. Person has parameters name,birthdate,gender,age. I created lists for first names and last names from which i am randomly selecting name. Can someone help me?
Here is my code:
#docker params
name="`docker ps | rev | cut -d " " -f1 | rev | grep -v NAMES`"
dbs_name="DBS_projekt"
#load names from files
firstName=(`cat generatorSource/firstNames.txt`)
firstNameCount="`wc -l generatorSource/firstNames.txt | tr -s ' ' | cut -d ' ' -f2`"
secondName=(`cat generatorSource/lastNames.txt`)
secondNameCount="`wc -l generatorSource/lastNames.txt| tr -s ' ' | cut -d ' ' -f2`"
#gender array
gender=("Male" "Female" "Other")
#actual date
now=$(date | rev | cut -d " " -f1 | rev)
array=()
for ((x = 1; x <= 1000;x++))
do
array+="INSERT INTO persons(name,birthdate,gender,age) VALUES"
for (( n=1; n<=1000; n++ ))
do
secondrand=$(( ( RANDOM % $secondNameCount ) ))
firstrand=$(( ( RANDOM % $firstNameCount ) ))
genderand=$(( ( RANDOM % 3 ) ))
year=$(( ( RANDOM % 118 ) + 1900 ))
month=$(((RANDOM % 12) + 1))
day=$(((RANDOM % 28) + 1))
age=$(expr $now - $year)
if [ $n -eq 1000 ]; then
array+="('${firstName[$firstrand]}
${secondName[$secondrand]}','$year-$month-$day',
'${gender[$genderand]}','$age');"
else
array+="('${firstName[$firstrand]}
${secondName[$secondrand]}','$year-$month-$day',
'${gender[$genderand]}','$age'),"
fi
done
done
#run psql in docker and run insert commands
docker exec -i $name psql -U postgres << EOF
\c $dbs_name
$array
EOF
Note that you declare "array" as an array, but you use it as a string.
array=()
...
array+="INSERT INTO persons(name,birthdate,gender,age) VALUES"
This is what's happening:
$ array=()
$ declare -p array
declare -a array='()'
$ array+="first"
$ array+="second"
$ declare -p array
declare -a array='([0]="firstsecond")'
To insert an element into an array, you must use parentheses:
$ array=()
$ array+=("first")
$ array+=("second")
$ declare -p array
declare -a array='([0]="first" [1]="second")'
I suspect this may be one source of slowness: you're constructing one gigantic string. Add the parentheses as shown, and then change the docker call to
IFS=$'\n'
docker exec -i $name psql -U postgres << EOF
\c $dbs_name
${array[*]}
EOF

BASH execute command on remote server

I want to execute a command which return all user's home directory that exist and store the result into bash variable
res=$(ssh -q -o LogLevel=error user#server << 'EOF'
t=$(awk -F':' '{ if ( $3 >= 500 ) print $1 }' /etc/passwd)
readarray -t res_array <<< "${t}"
UHOME="/home"
for u in "$res_array"
do
_dir="${UHOME}"/"${u}"
if [[ -d "$_dir" ]]
then
echo "$u"
fi
done
EOF
)
locally the code works but not on remote server
I used echo $u for store the resultat home user exist to the variable :(
do this:
res=$(ssh -q -o LogLevel=error user#server << 'EOF'
t=$(awk -F':' '{ if ( $3 >= 500 ) print $1 }' /etc/passwd)
readarray -t res_array <<< "${t}"
UHOME="/home"
for u in "${res_array[#]}" # change this line
do
_dir="${UHOME}"/"${u}"
if [[ -d "$_dir" ]]
then
echo "$u"
fi
done
EOF
)

Read delimited multiline string file into multiple arrays in Bash

I began with a file like so:
Table_name1 - Table_desc1
Table_name2 - Table_desc2
...
...
I have a script that parses this file and splits them into two arrays:
declare -a TABLE_IDS=()
declare -a TABLE_DESCS=()
while IFS= read -r line || [[ -n "${line}" ]]; do
TABLE_IDS[i]=${line%' '-' '*}
TABLE_DESCS[i++]=${line#*' '-' '}
done < "${TABLE_LIST}"
for i in "${!TABLE_IDS[#]}"; do
echo "Creating Table ID: "${TABLE_IDS[i]}", with Table Description: "${TABLE_DESCS[i]}""
done
This works really well, with no problems whatsoever.
I wanted to extend this and make the file:
Table_name1 - Table_desc1 - Table_schema1
Table_name2 - Table_desc2 - Table_schema2
...
...
For this, I tried:
declare -a TABLE_IDS=()
declare -a TABLE_DESCS=()
while IFS= read -r line || [[ -n "${line}" ]]; do
TABLE_IDS[i]="$(echo $line | cut -f1 -d - | tr -d ' ')"
TABLE_DESCS[i++]="$(echo $line | cut -f2 -d - | tr -d ' ')"
TABLE_SCHEMAS[i++]="$(echo $line | cut -f3 -d - | tr -d ' ')"
done < "${TABLE_LIST}"
for i in "${!TABLE_IDS[#]}"; do
echo "Creating Table ID: "${TABLE_IDS[i]}", with Table Description: "${TABLE_DESCS[i]}" and schema: "${TABLE_SCHEMAS[i]}""
done
And while this will faithfully list all the Table IDs and the Table descriptions, the schemas are omitted. I tried:
while IFS= read -r line || [[ -n "${line}" ]]; do
TABLE_IDS[i]="$(echo $line | cut -f1 -d - | tr -d ' ')"
TABLE_DESCS[i]="$(echo $line | cut -f2 -d - | tr -d ' ')"
TABLE_SCHEMAS[i]="$(echo $line | cut -f3 -d - | tr -d ' ')"
done < "${TABLE_LIST}"
And it returns just the last line's Table name, description AND schema. I suspect this is an indexing/looping problem, but am unable to figure out what exactly is going wrong. Please help! Thanks!
perhaps set the delimiter to the actual delimiter - and do the processing in the read loop instead of deferring and using arrays.
$ while IFS=- read -r t d s;
do
echo "Creating Table ID: ${t// }, with Table Description: ${d// } and schema: ${s// }";
done < file

How do you reference a variable within another variable in bash?

I am trying to do something which I thought would be fairly simple but not having any joy.
If I run the following, it successfully pulls the region (reg) from an array called PORT330 and checks to see it contains the value of $i. For example, it could be checking to see if "Europe London" contains the word "London". Here is what works:
if [[ ${PORT330[reg]} == *"$i"* ]] ; then
echo 302 is in $i ;
fi
However, I actually have a list of Port array's to check so it may be PORT330, PORT550 and so on. I want to be able to substitute the port number with a variable but then call it within a variable. Here is what I am trying to do:
This works:
for portid in ${portids[#]} ; do
for i in ${regions[#]} ; do
if [[ ${PORT330[reg]} == *"$i"* ]] ; then
echo $portid is in $i ;
fi ;
done ;
done
However this doesn't work:
for portid in ${portids[#]} ; do
for i in ${regions[#]} ; do
if [[ ${PORT$portid[reg]} == *"$i"* ]] ; then
echo $portid is in $i ;
fi ;
done ;
done
It throws this error:
-su: ${PORT$portid[reg]}: bad substitution
Any pointers as to where I am going wrong?
In BASH variable expansion there is an option to have indirection via the ${!name} and ${!name[index]} schemes
for portid in ${portids[#]} ; do
for i in ${regions[#]} ; do
arr=PORT$portid
if [[ ${!arr[reg]} == *"$i"* ]] ; then
echo $portid is in $i ;
fi ;
done ;
done
Here is a complete example
PORT330[reg]=a ;
PORT550[reg]=b ;
for portid in 330 550 ; do
for i in a b ;
do arr=PORT$portid ;
if [[ ${!arr[reg]} == *"$i"* ]] ; then
echo $portid is in $i ;
fi ;
done ;
done
Produces
330 is in a
550 is in b
Another example
:~> portids=(330 350 )
:~> echo ${portids[#]}
330 350
:~> PORT350[reg]=London
:~> PORT330[reg]=Berlin
:~> for portid in ${portids[#]} ; do arr=PORT$portid ; echo ${!arr[reg]} ; done
Berlin
London

Resources