im trying to send the message content in a variable to an sh script, to trigger this i start the telegram message with the word "test"
i have this in my lua script that i run with telegram on my odroid
-- TEST:
action, variable=msg.text:match("+ %b %s")
if (action=='test' or action=='Test') then
os.execute(string.format("/home/scripts/test.sh \"%s\" &",variable))
if i send: "test i want this text in the variable"
via telegram to the odroid, it does nothing.
i have tried a lot of variations on ("+ %b %s") however it does not work
any idea what im doing wrong?
ps. the trigger word "test" must not be saved to the variable
The standard way to pass a string as command line parameter is the following:
variable = msg.text:match"^[Tt]est%s*(.*)$"
if variable then
os.execute("/home/scripts/test.sh '"..variable:gsub("'", "'\\''").."'&")
end
How does test.sh processing the string? The problem of disappearing spaces might be there.
Related
readLine() doesn't support line editing and recalling previous commands, eg:
while true:
var name: string = readLine(stdin)
echo "Hi, ", name, "!"
Has no editing. But if I compile that and wrap it in rlwrap:
$ rlwrap read_test
It works as I hope. with editable and recallable lines, provided by the readline library.
readLineFromStdin() almost works, but doesn't support ctrl+d, it returns an empty string on ctrl+d, which is indistinguishable from a newline.
How can I do this in pure Nim? Thanks!
Ctrl+D is an EOF "signal", and thus you can catch the EOF in your input:
while not endOfFile(stdin):
var name: string = readLine(stdin)
echo "Hi, ", name, "!"
The procedure readLineFromStdin (https://github.com/nim-lang/Nim/blob/version-1-2/lib/impure/rdstdin.nim#L54) is not that complex, and you can re-write your own adding the above code to it.
While #xbello's answer is correct, if you want to use a package, we ended up using https://github.com/jangko/nim-noise, which supports C-d handling and loads of other features.
I need to automate a huge interactive Tcl program using Tcl expect.
As I realized, this territory is really dangerous, as I need to extend the already existing mass of code, but I can't rely on errors actually causing the program to fail with a positive exit code as I could in a regular script.
This means I have to think about every possible thing that could go wrong and "expect" it.
What I currently do is use a "die" procedure instead of raising an error in my own code, that automatically exits. But this kind of error condition can not be catched, and makes it hard to detect errors especially in code not written by me, since ultimately, most library routines will be error-based.
Since I have access to the program's Tcl shell, is it possible to enable fail-on-error?
EDIT:
I am using Tcl 8.3, which is a severe limitation in terms of available tools.
Examples of errors I'd like to automatically exit on:
% puts $a(2)
can't read "a(2)": no such element in array
while evaluating {puts $a(2)}
%
% blublabla
invalid command name "blublabla"
while evaluating blublabla
%
As well as any other error that makes a normal script terminate.
These can bubble up from 10 levels deep within procedure calls.
I also tried redefining the global error command, but not all errors that can occur in Tcl use it. For instance, the above "command not found" error did not go through my custom error procedure.
Since I have access to the program's Tcl shell, is it possible to
enable fail-on-error?
Let me try to summarize in my words: You want to exit from an interactive Tcl shell upon error, rather than having the prompt offered again?
Update
I am using Tcl 8.3, which is a severe limitation in terms of available
tools [...] only source patches to the C code.
As you seem to be deep down in that rabbit hole, why not add another source patch?
--- tclMain.c 2002-03-26 03:26:58.000000000 +0100
+++ tclMain.c.mrcalvin 2019-10-23 22:49:14.000000000 +0200
## -328,6 +328,7 ##
Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
Tcl_WriteChars(errChannel, "\n", 1);
}
+ Tcl_Exit(1);
} else if (tsdPtr->tty) {
resultPtr = Tcl_GetObjResult(interp);
Tcl_GetStringFromObj(resultPtr, &length);
This is untested, the Tcl 8.3.5 sources don't compile for me. But this section of Tcl's internal are comparable to current sources, tested using my Tcl 8.6 source installation.
For the records
With a stock shell (tclsh), this is a little fiddly, I am afraid. The following might work for you (though, I can imagine cases where this might fail you). The idea is
to intercept writes to stderr (this is to where an interactive shell redirects error messages, before returning to the prompt).
to discriminate between arbitrary writes to stderr and error cases, one can use the global variable ::errorInfo as a sentinel.
Step 1: Define a channel interceptor
oo::class create Bouncer {
method initialize {handle mode} {
if {$mode ne "write"} {error "can't handle reading"}
return {finalize initialize write}
}
method finalize {handle} {
# NOOP
}
method write {handle bytes} {
if {[info exists ::errorInfo]} {
# This is an actual error;
# 1) Print the message (as usual), but to stdout
fconfigure stdout -translation binary
puts stdout $bytes
# 2) Call on [exit] to quit the Tcl process
exit 1
} else {
# Non-error write to stderr, proceed as usual
return $bytes
}
}
}
Step 2: Register the interceptor for stderr in interactive shells
if {[info exists ::tcl_interactive]} {
chan push stderr [Bouncer new]
}
Once registered, this will make your interactive shell behave like so:
% puts stderr "Goes, as usual!"
Goes, as usual!
% error "Bye, bye"
Bye, bye
Some remarks
You need to be careful about the Bouncer's write method, the error message has already been massaged for the character encoding (therefore, the fconfigure call).
You might want to put this into a Tcl package or Tcl module, to load the bouncer using package req.
I could imagine that your program writes to stderr and the errorInfo variable happens to be set (as a left-over), this will trigger an unintended exit.
I have a test script I'm running that generates some errors,shown below, I expect these errors. Is there anyway I can prevent them from showing on the screen however? I use the
$ write sys$output
to display if there is an expected error.
I tried to use
$ DEFINE SYS$ERROR ERROR.LOG
but this then changed my entire error output log to this, if this is the correct way to handle it can I unset this at the end of my script somehow?
[error example]
%DCL-E-OPENIN, error opening TEST$DISK:[AAA]NOTTHERE.TXT; as input
-RMS-E-FNF, file not found
%DCL-E-OPENIN, error opening TEST$DISK:[AAA]NOTTHERE.TXT; as input
-RMS-E-FNF, file not found
%DCL-W-UNDFIL, file has not been opened by DCL - check logical name
DEFINE/USER creates a logical name that disappears when the next image exits.
So if you use that just before a command just to protect that command, then fine.
Otherwise I would prefer SET MESSAGE to control the output.
And of course yoy want to grab $STATUS and verify it after the command for success or for the expected error, reporting any unexpected error.
Better still... if you expect certain error conditions to occur,
then why not test for them?
For example:
$ file = F$SEARCH("TEST$DISK:[AAA]NOTTHERE.TXT")
$ IF file.NES."" THEN TYPE 'file'
Cheers,
Hein
To suppress Error message inside a script. try this command
$ DEFINE/USER SYS$ERROR NL:
NL: is a null device, so you don`t see any error messages displayed on your terminal.
good luck
This works interactively and in batch.
$ SET MESSAGE /NOTEXT /NOSEV /NOFAC /NOID
$ <DCL_Command>
$ SET MESSAGE /TEXT /SEV /FAC/ ID
I'm trying to run an script to connect to a Procurve 4204vl switch using expect.
This is the code I created:
#!/usr/bin/expect -f
set timeout 20
spawn ssh -l user 192.168.0.10
expect "user#192.168.0.10's password:"
send "1234"
send "\r"
expect "Press any key to continue"
send "j\r"
send "conf"
send "\r"
send "no ip route 89.19.238.2 255.255.255.255 192.168.0.12"
send "\r"
send "exit"
send "\r"
send "exit"
send "\r"
send "exit"
send "\r"
expect "Do you want to log out [y/n]?"
send "y"
I run this using simply expect script.exp, and the problem is I got these errors:
the route is not deleted
I got the following error on screen after the script execution is finished:
Press any key to continue invalid command name "y/n"
while executing
"y/n"
invoked from within
"expect "Do you want to log out [y/n]?""
(file "script.exp" line 19)
So, how could I solve this problem?
Thank you.
PS: if I comment all the "exit" lines and also the log out question, then add a last line with the "interact" command, the script works fine.
For route not deleted, what output is the program giving you? Do you see any errors from the router?
In expect and Tcl the square brackets are the syntax to execute a command, quite like backticks in the shell. The simplest solution is to use braces instead of double quotes to prevent command interpolation:
expect {Do you want to log out [y/n]?}
Braces act like single quotes in the shell.
send "logout\r"
expect {
"Do you want to log out" {
send "yy"
exp_continue
} "Do you want to save current configuration" {
set result $expect_out(0,string);
puts "save..."
send "y"
puts "ok"
} eof {
puts "end of script"
}
}
What it worked for me is to use regex (-re argument) and avoid using the characters [] in the expression:
expect -re "Do you want to log out"
It's also useful because if the output from the command is too long or dynamic, using static expression is limited.
What's the best way to append the content of a string variable from a Vim script?
If variable contains no newlines, then use
call append(line('$'), [variable])
, you can also do
call append(line('$'), split(variable, "\n"))
,
execute "normal! Go".variable
, or
execute "normal! Go\<C-r>\<C-r>=variable\<CR>"
You could also put the variable into a register like this:
let #a = variable
normal! G
execute "put a"
This works with or without carriage returns.