TCL regsub to variable? - variables

I'm setting up macros, Set, and Say. Defined in procedures.
proc Set {key value args} {
set ::$key $value
set "::key2" "$key"
}
proc Say {key} {
puts $key
}
proc Say2 {key} {
set key3 [regsub "\%" $key "\$"]
puts $key3
eval puts $key3
}
Which allows me to execute the following:
Set "test" "this should display this test text"
Say $key2 ;#should display the key "test" which is what we just set
Say $test ;#presents the value of the key test
Output
% Set "test" "this should display this test text"
test
% Say $key2 ;#should display the key "test" which is what we just set
test
% Say $test ;#presents the value of the key test
this should display this test text
So now lets say I want to reassign the variable $ to %
Set "mouse" "squeak" ;#set key mouse with value string of "squeak"
Say $mouse ;#displays the value as set above correctly
Say2 %mouse ;#start using our own characters to represent variables - switch the % for a $ and then output
However I then get when using eval,
can't read "mouse": no such variable
Output
% Set "mouse" "squeak" ;#set key mouse with value string of "squeak"
mouse
% Say $mouse ;#displays the value as set above correctly
squeak
% Say2 %mouse ;#start using our own characters to represent variables
$mouse
can't read "mouse": no such variable
I'm finding this weird because we set it above, we can recall the value using the standard $ And I can prove that the regsub in Say2 is working as it should replacing % with $.
%mouse becomes $mouse which is a valid variable.
Eval $mouse outputs with no such variable
Am I missing something?
Thanks

The issue is with the proc:
proc Say2 {key} {
set key3 [regsub {%} $key {$}]
puts $key3
eval puts $key3 ;# here
}
$mouse does not exist in this proc. It was not passed as a parameter, nor was it created with set. It exists however in the global namespace. One way to reach for it is to use uplevel in this case:
proc Say2 {key} {
set key3 [regsub {%} $key {$}]
puts $key3
uplevel puts $key3
}
Another option I often use is upvar to bring the variable inside (though in this case, we don't want the $ anymore):
proc Say2 {key} {
set key3 [regsub {%} $key {}]
puts $key3
upvar $key3 var
puts $var
}
PS: I also went ahead and removed some backslashes since they aren't really needed in that scenario.

Related

jenkins on windows. Declarative pipeline jenkinsfile. how to set and get correct variable values

I use Jenkinsefile file to run the Stages.
It is in Jenkins pipeline installed on windows, Declarative pipeline.
On the begining I do:
pipeline {
agent { label 'master'}
environment {
My_build_result = 7
}
....
Than
stage('Test') {
steps {
echo 'Testing..'
bat """
cd Utils
"C:\\Program Files\\MATLAB\\R2019b\\bin\\matlab.exe" -wait -nodisplay -nosplash -nodesktop -r "run('automatic_tests\\run_test.m');"
echo %errorlevel%
set /a My_build_result_temp = %errorlevel%
set My_build_result = %My_build_result_temp%
"""
script {
My_build_result = bat(returnStatus:true , script: "exit (2)").trim()
echo "My_build_result ${env.My_build_result}"
if (My_build_result != 0) {
echo "inside if"
}
}
}
}
The variable My_build_result get value 7 at the begining
Inside the bat section, it suppose to get value 0 from %errorlevel%
Inside the script section it suppose to get value 2
BUT
in the echo "My_build_result ${env.My_build_result}" I get print of 7
(and it goes inside the if sentense)
How do I define variable that can be set value in bat"""
"""
and in script """
"""
section of the stage
and also be familiar in another stages and in the post { always { .. }} at the end ???
BTW: add env.before My_build_result (env.My_build_result ) does not work
Thanks a lot
In the first bat call, you are setting the environment variable only inside of the batch script environment. Environment variable values that are assigned through set don't persist when the script ends. Think of these like local variables. Simply use returnStatus: true to return the last value of ERRORLEVEL. There is no need to use %ERRORLEVEL% in the batch script here.
steps {
script {
My_build_result = bat returnStatus: true, script: """
cd Utils
"C:\\Program Files\\MATLAB\\R2019b\\bin\\matlab.exe" -wait -nodisplay -nosplash -nodesktop -r "run('automatic_tests\\run_test.m');"
"""
// My_build_result now has the value of ERRORLEVEL from the last command
// called in the batch script.
}
}
In the 2nd bat call the 1st mistake is to call the trim() method. Result type of bat step is Integer, when returnStatus: true is passed. The trim() method is only available when returnStdout: true is passed in which case the result type would be String. The 2nd mistake is to use brackets around the exit code value. The fixed code should look like:
My_build_result = bat returnStatus: true, script: "exit 2"
// My_build_result now equals 2

perl6 Unable to initialize a state variable. Help needed

I want to use a one-liner to print a middle section of a file by using a state variable to indicate whether the current line is within the desired section of the file. But I am unable to initialize the state variable. Initialization is so simple, and I just cannot find what the problem is. Please help. Thanks.
The file is name testFile.txt and has the following lines:
section 0; state 0; not needed
= start section 1 =
state 1; needed
= end section 1 =
section 2; state 2; not needed
And my one-liner is
cat testFile.txt | perl6 -ne ' state $x = 0; say "$x--> "; if $_ ~~ m/ "start" / { $x=1; }; if $x == 1 { .say; }; if $_ ~~ m/ "end" / { $x = 2; }'
And the output showed that $x=0 is not doing initialization:
Use of uninitialized value $x of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block at -e line 1
-->
Use of uninitialized value of type Any in numeric context
in block at -e line 1
Use of uninitialized value $x of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block at -e line 1
-->
= start section 1 =
1-->
state 1; needed
1-->
= end section 1 =
2-->
2-->
This looks like a bug to me: Apparently, -n does not properly set up a lexical environment.
As a workaround, you can wrap the whole things in a block, eg by surrounding your code with do { ... } or even just { ... }.
Also note that depending on your use case, the whole thing can probably be simplified by using the flip-flop operator, eg
cat testFile.txt | perl6 -ne '.say if / "start" / ff / "end" /'

Dynamic variable and value assignment in powershell

How can I declare variables and assign values to them at run time.
Reason: I am fetching these variables values from sql server and these variable values are configurable in nature
Code which I have tried till now
[array]$varArray = #($($ServerName),$($HostName))
foreach($varname in $varArray)
{
$varname = "some test value"
}
Write-Host $ServerName
Write-Host $HostName
The simplest way of using dynamically named variables would be a dictionary:
$vars = #{} # create empty dictionary
# add key/value pairs to dictionary:
$vars["foo"] = 23
$vars["bar"] = "foobar"
$vars["baz"] = Get-Content C:\sample.txt
Another way would be to declare variables on the fly:
$name = "foo"
$value = "bar"
New-Variable $name $value
echo $foo
Or you could create a custom object and add properties as Kyle C suggested. That approach is similar to a dictionary, although technically different.
You could try adding a NoteProperty to the object.
$varname | Add-Member -type NoteProperty -name TestProperty -value "some test value" -PassThru
Also see this for what types of objects you can add a member to: What objects are suitable for Add-Member?

Break down JSON string in simple perl or simple unix?

ok so i have have this
{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}
and at the moment i'm using this shell command to decode it to get the string i need,
echo $x | grep -Po '"utterance":.*?[^\\]"' | sed -e s/://g -e s/utterance//g -e 's/"//g'
but this only works when you have a grep compiled with perl and plus the script i use to get that JSON string is written in perl, so is there any way i can do this same decoding in a simple perl script or a simpler unix command, or better yet, c or objective-c?
the script i'm using to get the json is here, http://pastebin.com/jBGzJbMk and if you want a file to use then download http://trevorrudolph.com/a.flac
How about:
perl -MJSON -nE 'say decode_json($_)->{hypotheses}[0]{utterance}'
in script form:
use JSON;
while (<>) {
print decode_json($_)->{hypotheses}[0]{utterance}, "\n"
}
Well, I'm not sure if I can deduce what you are after correctly, but this is a way to decode that JSON string in perl.
Of course, you'll need to know the data structure in order to get the data you need. The line that prints the "utterance" string is commented out in the code below.
use strict;
use warnings;
use Data::Dumper;
use JSON;
my $json = decode_json
q#{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}#;
#print $json->{'hypotheses'}[0]{'utterance'};
print Dumper $json;
Output:
$VAR1 = {
'status' => 0,
'hypotheses' => [
{
'utterance' => 'hello how are you',
'confidence' => '0.96311796'
}
],
'id' => '7aceb216d02ecdca7ceffadcadea8950-1'
};
Quick hack:
while (<>) {
say for /"utterance":"?(.*?)(?<!\\)"/;
}
Or as a one-liner:
perl -lnwe 'print for /"utterance":"(.+?)(?<!\\)"/g' inputfile.txt
The one-liner is troublesome if you happen to be using Windows, since " is interpreted by the shell.
Quick hack#2:
This will hopefully go through any hash structure and find keys.
my $json = decode_json $str;
say find_key($json, 'utterance');
sub find_key {
my ($ref, $find) = #_;
if (ref $ref) {
if (ref $ref eq 'HASH' and defined $ref->{$find}) {
return $ref->{$find};
} else {
for (values $ref) {
my $found = find_key($_, $find);
if (defined $found) {
return $found;
}
}
}
}
return;
}
Based on the naming, it's possible to have multiple hypotheses. The prints the utterance of each hypothesis:
echo '{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}' | \
perl -MJSON::XS -n000E'
say $_->{utterance}
for #{ JSON::XS->new->decode($_)->{hypotheses} }'
Or as a script:
use feature qw( say );
use JSON::XS;
my $json = '{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}';
say $_->{utterance}
for #{ JSON::XS->new->decode($json)->{hypotheses} };
If you don't want to use any modules from CPAN and try a regex instead there are multiple variants you can try:
# JSON is on a single line:
$json = '{"other":"stuff","hypo":[{"utterance":"hi, this is \"bob\"","moo":0}]}';
# RegEx with negative look behind:
# Match everything up to a double quote without a Backslash in front of it
print "$1\n" if ($json =~ m/"utterance":"(.*?)(?<!\\)"/)
This regex works if there is only one utterance. It doesn't matter what else is in the string around it, since it only searches for the double quoted string following the utterance key.
For a more robust version you could add whitespace where necessary/possible and make the . in the RegEx match newlines: m/"utterance"\s*:\s*"(.*?)(?<!\\)"/s
If you have multiple entries for the utterance confidence hash/object, changing case and weird formatting of the JSON string try this:
# weird JSON:
$json = <<'EOJSON';
{
"status":0,
"id":"an ID",
"hypotheses":[
{
"UtTeraNcE":"hello my name is \"Bob\".",
"confidence":0.0
},
{
'utterance' : 'how are you?',
"confidence":0.1
},
{
"utterance"
: "
thought
so!
",
"confidence" : 0.9
}
]
}
EOJSON
# RegEx with alternatives:
print "$1\n" while ( $json =~ m/["']utterance["']\s*:\s*["'](([^\\"']|\\.)*)["']/gis);
The main part of this RegEx is "(([^\\"]|\\.)*)". Description in detail as extended regex:
/
["'] # opening quotes
( # start capturing parentheses for $1
( # start of grouping alternatives
[^\\"'] # anything that's not a backslash or a quote
| # or
\\. # a backslash followed by anything
) # end of grouping
* # in any quantity
) # end capturing parentheses
["'] # closing quotes
/xgs
If you have many data sets and speed is a concern you can add the o modifier to the regex and use character classes instead of the i modifier. You can suppress the capturing of the alternatives to $2 with clustering parenthesis (?:pattern). Then you get this final result:
m/["'][uU][tT][tT][eE][rR][aA][nN][cC][eE]["']\s*:\s*["']((?:[^\\"']|\\.)*)["']/gos
Yes, sometimes perl looks like a big explosion in a bracket factory ;-)
Just stubmled upon another nice method of doing this, i finaly found how to acsess the Mac OS X JavaScript engine form commandline, heres the script,
alias jsc='/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Resources/jsc'
x='{"status":0,"id":"7aceb216d02ecdca7ceffadcadea8950-1","hypotheses":[{"utterance":"hello how are you","confidence":0.96311796}]}'
jsc -e "print(${x}['hypotheses'][0]['utterance'])"
Ugh, yes i came up with another answer, im strudying python and it reads arrays in both its python format and the same format as a json so, i jsut made this one liner when your variable is x
python -c "print ${x}['hypotheses'][0]['utterance']"
figured it out for unix but would love to see your perl and c, objective-c answers...
echo $X | sed -e 's/.*utterance//' -e 's/confidence.*//' -e s/://g -e 's/"//g' -e 's/,//g'
:D
shorter copy of the same sed:
echo $X | sed -e 's/.*utterance//;s/confidence.*//;s/://g;s/"//g;s/,//g'

Variable expansion and escaped characters

In PowerShell, you can expand variables within strings as shown below:
$myvar = "hello"
$myvar1 = "$myvar`world" #without the `, powershell would look for a variable called $myvarworld
Write-Host $myvar1 #prints helloworld
The problem I am having is with escaped characters like nr etc, as shown below:
$myvar3 = "$myvar`albert"
Write-Host $myvar3 #prints hellolbert as `a is an alert
also the following doesnt work:
$myvar2 = "$myvar`frank" #doesnt work
Write-Host $myvar2 #prints hellorank.
Question:
How do I combine the strings without worrying about escaped characters when I am using the automatic variable expansion featurie?
Or do I have to do it only this way:
$myvar = "hello"
$myvar1 = "$myvar"+"world" #using +
Write-Host $myvar1
$myvar2 = "$myvar"+"frank" #using +
This way is not yet mentioned:
"$($myvar)frank"
And this:
"${myvar}frank"
This seems kind of kludgy, but as another option, you can add a space and a backspace:
$myvar = "hello"
$myvar1 = "$myvar `bworld"
$myvar1
Yet another option is to wrap your variable expression in a $():
$myvar3 = "$($myvar)albert"
Write-Host $myvar3
One other option is through the format operator:
"{0}world" -f $myvar
Another option is a double-quoted here-string:
$myvar = "Hello"
$myvar2 = #"
$myvar$("frank")
"#