Can Org-Babel code be converted to Elisp? - emacs

I have an org-babel source, which accesses a server via tramp and runs a shell script there. Is it possible to convert this source block into an Elisp function?
#+BEGIN_SRC sh :dir "/pscp:putty-connection-xy:/dir-yz"
expect -c '
spawn bash -c "scp file-to-copy user#server:/home1/dir-xy"
expect {
"(yes/no)?" {
send "yes\r"
expect "*?assword:*"
send "secretPassWord\r"
}
"*?assword:*" {
send "secretPassWord\r"
}
}
expect eof
'
#+END_SRC

Use Tramp's multi-hop (untested):
(copy-file "/plink:putty-connection-xy:/dir-yz/file-to-copy"
"/plink:putty-connection-xy|ssh:user#server:/home1/dir-xy/")
This uses plink and ssh, 'tho. If you can connect user#server directly from your local machine, you could shorten this, using pscp:
(copy-file "/pscp:putty-connection-xy:/dir-yz/file-to-copy"
"/pscp:user#server:/home1/dir-xy/")

The solution is simple. I call the block and give it over
'sh', the code and the parameters of the block. It works
(org-babel-execute-src-block nil
'("sh"
"cd /home1/
expect -c '
spawn bash -c \"scp file-to-copy user#server:/home1/dir-xy .\"
expect {
\"*?assword:*\" {
send \"secretPassWord\\r\" } }
expect eof'
"
((:colname-names) (:rowname-names)
(:result-params "raw" "replace")
(:result-type . value) (:results . "silent")
(:exports . "code")
(:tangle . "no") (:hlines . "no") (:noweb . "no")
(:cache . "no") (:session . "none")) "" nil nil ))

Related

validate only alphabets using shell script in busybox

I want to validate a string which should only be Alphabets (Capital/Small). I can do it in Linux easily using Bash or Shell, but not able to validate in Busybox (OpenWRT). My piece of code is
...
#!/bin/sh
. /usr/share/libubox/jshn.sh
Info=$(cat /root/Info.json)
json_load "$Info"
json_get_var value plmn_description
echo "$value"
if [[ "$value" == [a-zA-Z] ]] ;then
echo "Valid"
else
echo "Invalid information"
fi
...
You can use case conditional construct like this:
case "$value" in
*[!a-zA-Z]*) echo invalid information ;;
*) echo valid
esac
Using Busybox awk:
$ busybox awk '{ # using busybox awk
for(i=1;i<NF;i++) # iterate all json record fields (not the last, thou)
if($i=="\"plmn_description\":" && $(i+1)~/^\"[a-zA-Z]+\",?$/) {
ret="Valid" # if "plmn_description": is followed by "alphabets"
exit # exit for performance
}
}
END {
print (ret?ret:"Invalid") # output Valid or Invalid
}' Info.json # process the json file
Output:
Valid

Code fails with stdin from SED

I have a bash script that finds files with particular extension and then pass the files into a function that checks every line in the file for only files that contain a library imported. For example:
function testing() {
while IFS='' read -r line; do
if [[ "$line" =~ .*log\" ]]; then
echo "log is imported in the file" $1
break
else
echo "log is not imported in the file" $1
break
fi
done < <(sed -n '/import (/,/)/p' "$1")
}
function main() {
for file in $(find "$1" -name "*.go"); do
if [[ $file == *test.go ]]; then
:
else
var1=$(testing $file)
echo "$var1"
fi
done;
}
main $1
The problem is the script works without the else block in the testing function but with the introduction of the else block in the testing function it just defaults to echoing the log is not imported in the file blah even if log is used in some of the files.
Any idea(s) on what is the problem?
Thanks.
Here is a sample input file:
package main
import (
"fmt"
"io/ioutil"
logger "log"
"net/http"
)
type webPage struct {
url string
body []byte
err error
}
...
And the output is basically to echo if log is imported or not.
You need to rewrite the logic of your testing function as it will only test the first line of the file. Indeed, each branch of the if [[ "$line" =~ .*log\" ]] has a break statement, so in practice, a break is reached whenever the first line is read.

if condition using telnet in perl not working

I'm trying to use if condition to check if command has passed, but its not working. Even though the mount has been successful it goes to failed message. When i enter this command, it retruns to the prompt without any message, hence i'm comparing with a "". And when i do a "ls" of destination folder, it shows all contents of source folder. Any help? Is my if condition correct?
my $port = new Net::Telnet->new(Host=>$ip,Port=>$ip_port,Timeout => "$timeout", Dump_Log => "dumplog.log", Errmode=> "return" );
if($port->cmd("mount -t nfs -o nolock <path-of-source-folder> <destination-folder>") eq "")
{
print "Successful\n";
}
else{
print "Failed.\n ";
}
In scalar context, the Net::Telnet cmd method returns 1 on success (not a string). Your check should be something like:
if ($port->cmd("mount -t nfs -o nolock <path-of-source-folder> <destination-folder>") == 1)
{
print "Successful\n";
} else {
print "Failed.\n";
}
If you actually want to collect the output from the mount command and inspect it, you will have to either call it in list context or pass a stringref argument, like so:
my #outlines = $port->cmd("mount ...");
Or:
my $out;
my $ret = $port->cmd("mount ...", [Output => \$out]);
if ($ret == 1)
{
# inspect $out
}
See the Net::Telnet documentation for more.
Your check for the result seems to be wrong. The documenation of Net::Telnet says that
This method sends the command $string, and reads the characters sent back by the command up until and including the matching prompt. It's assumed that the program to which you're sending is some kind of command prompting interpreter such as a shell.
The command $string is automatically appended with the output_record_separator, by default it is "\n". This is similar to someone typing a command and hitting the return key. Set the output_record_separator to change this behavior.
In a scalar context, the characters read from the remote side are discarded and 1 is returned on success.
So you need to check in a scalar context
if ($port->cmd("..") ) {
...
}

Sed : Add a line at the starting of each TCL proc

I have a TCL proc like this, & want to add a line after the start of the proc, the puts "puts " entered myproc" " line
proc myproc { {filename "input.txt"}
{var1 "x"}
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"
Can you help?
& it should also work for
proc myproc2 { N val } {
puts " entered myproc"
# comment line
set ret {} for { set i 0 } { $i < $N } { incr i } { lappend ret $val }
return $ret
}
If all you want to do is get an execution trace of your code, such as a call stack dump etc, then you don't need to modify your source code at all. You can use tcl itself to do it for you.
Tcl has no reserved keywords, none at all. Not even proc is reserved. You can therefore redefine it:
rename proc _proc
# Now proc no longer exists but we have _proc instead.
# Use it to redefine "proc":
_proc proc {name arguments body} {
set body "puts \"entered $name\";$body"
_proc $name $arguments $body
}
Just do that before running any of your own code and you'll find that every proc prints out when it's being entered on each call.
This is how a lot of tcl debuggers and profilers work - using tcl to redifine itself.
From your comments it looks like you're trying to also print how deep the stack is with each call. To do that you need to add more code to each proc definition. The most straightforward way is of course something like this:
_proc proc {name arguments body} {
set preamble"set dist2top \[info level\];puts \"\$dist2top entered $name\""
set body "$preamble;$body"
_proc $name $arguments $body
}
But as you can see, writing code inside strings can quickly become unmanagable. There are several tricks you can use to make it more manageable. One of the more common is to split $body by line and use list commands to manipulate code. It should reduce at least one level of quoting hell. My favorite is to use a templating technique similar to how you'd write html templates in MVC frameworks. I usually use string map for this:
_proc proc {name arguments body} {
_proc $name $arguments [string map [list %NAME% $name %BODY% $body] {
set dist2top [info level]
puts "$dist2top entered: %NAME%"
%BODY%
}]
}
The last argument in the _proc definition is just a string but it looks like a code block which makes it easier to read. No nasty quoting hell with this technique.
Using awk you can do:
awk '/^ *proc/ {$0 = $0 "\nputs \" entered myproc\""} 1' RS= proc-file.tcl
Gives this file:
proc myproc { {filename "input.txt"}
{var1 "x"}
{var2 "y"}
{var3 "z"}
{var4 ""}
{var5 "0"}
{var6 "0"}
{var7 0}
} {
puts " entered myproc"

How do I port a shell script to Perl?

This is a shell script , How do I accomplish the same thing in Perl?
prfile=~/sqllib/db2profile
profile()
{
if [ -f $prfile ] && [ "$prfile" != "" ];
then
. $prfile
else
read -p "Enter a valid Profile : " prfile
profile
fi
}
profile
Here it checks for the profile file , if found it executes it with . $prfile else it again asks user for the proper profile file
Update
#!/usr/bin/perl
use strict;
use warnings;
my $profile = "$ENV{'HOME'}/sqllib/db2proile";
# default profile
while (not -e $profile) { # until we find an existing file
print "Enter a valid profile: ";
chomp($profile = <>); # read a new profile
}
qx(. $profile);
This worked. I want the home directory to be dynamic rather than hardcoded as they differ for different machines. I'm just trying to accomplish with Perl what I have achieved with shell.
If I understand your objectives, I don't think you can use perl to accomplish this because perl will be running as a child process and it can not change the environment of your shell (it's parent process). Maybe this would work for you (untested, off the cuff)?
prfile=~/sqllib/db2profile
if [ -s "$prfile" ] ; then
. "$prfile"
else
while true ; do
read -p "Enter a valid Profile : " prfile
if [ -s "$prfile" ] ; then
. "$prfile"
break;
fi
done
fi