lua shell-less equivalent of `io.popen` - shell

Lua's io.popen is useful for capturing stdout of a command, but it relies on /bin/sh for word-splitting, glob expansion, etc.
So I can do the following and it works great
-- this unfortunately uses /bin/sh
local command = "ls -1";
local ph = io.popen(command, "r")
while true do
local line = ph:read()
if line == nil then
break
end
io.write("I read a line! " .. line .. "\n")
end
io.write("Done with line reading!\n")
Is there some function that's a thin wrapper around spawn* or fork/exec* that I can pass {"ls", "-1"} to in order to avoid the shell?

Related

Vargrantfile - Ruby - unexpected end of file

I am new to ruby. I was trying to modify existing Vargrantfile which is of ruby syntax.
I have below
def has_program(program)
ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory|
File.executable?(File.join(directory, program.to_s))
end
end
is_exist = has_program("some-command")
puts is_exist
$my_script = %{
if is_exist == false
if ! some-command status; then
#Do some staff
fi
end
# do some staff
}
Vagrant.configure("2") do |config|
node.vm.provision "shell", inline: $my_script
end
Then while running vagrant up --provision I am getting below error
syntax error: unexpected end of file
Can you please let me know what error I am doing?
With regards,
-M-
This is a syntax error but not one in your Ruby code as such. It's an unfinished statement in the shell code that you're executing from the Ruby script.
This can happen if you leave a block unclosed. The parser expects to find its end but encounters the end of the script instead.
Let's look at the part where you're executing a shell command
$my_script = %{
if is_exist == false
if ! some-command status; then
#Do some staff
fi
end
# do some staff
}
Now, let's strip the Ruby parts you have around it. The assignment $my_script = is still Ruby code. The part in curly braces is a string literal in the % notation that you later execute as a shell script using Vagrant's inline... However, it appears that you're switching back to Ruby syntax before ending the string literal.
What the interpreter parses as a shell script is this part:
if is_exist == false
if ! some-command status; then
#Do some staff
fi
end
# do some staff
Notice that the whole outer if expression uses Ruby's if syntax. It's not a valid shell command, hence the error.
I'm not sure what the semantics of this expression are in your case but you need to convert it to a shell if or move it outside the string literal you're passing to Vagrant using the inline option. On a side note, the logic inside seems strange. You're calling some-command if has_program("some-command") returns false. But that's a separate story :)

Unable to print array in bash shell

I have been using tcl shell on windows but while assisting someone on bash found a weird issue:
export SERVER_HOSTNAME=server1
export USERNAME=root
export PASSWORD=pswd
export LOG_FILE="a.log"
export LOG_PATH="$env(LOG_PATH)"
export log_search_pattern="Filterable_data"
/usr/bin/expect<<EOF
set lineNum {}
set SERVER_HOSTNAME "$env(SERVER_HOSTNAME)"
set USERNAME "$env(USERNAME)"
set PASSWORD "$env(PASSWORD)"
set LOG_FILE "$env(LOG_FILE)"
set log_search_pattern "$env(log_search_pattern)"
set timeout -1
spawn ssh "$USERNAME#$SERVER_HOSTNAME"
expect "assword:"
puts "$expect_out(buffer)"
parray expect_out
send "$PASSWORD\r"
expect "#"
puts "$expect_out(buffer)"
send "grep -n $log_search_pattern $LOG_PATH/$LOG_FILE|tail -1\r"
expect eof
EOF
Now the issue is that the following command:
puts "$expect_out(buffer)"
prints -> (buffer)
But prints the entire buffer contents
parray expect_out
I also tried adding following lines:
set a(1) val1
set a(2) val2
puts $a(1)
puts $a(2)
parray a
It printed:
(1)
(2)
a(1) = val1
a(2) = val2
I tried various combinations to get the puts $a(1) to print val1 but it always printed (1).
What's the correct method to do so?
Variables expand in HEREDOCs. If you want to avoid that you need to quote some or all of the opening HEREDOC marker (i.e. <<'EOF') (but not the closing one).
From Here Documents in the bash reference manual:
The format of here-documents is:
<<[-]word
here-document
delimiter
If any characters in word are quoted, the delimiter is the result of quote removal on word, and the lines in the here-document are not expanded.
So when you have:
puts "$expect_out(buffer)"
in the HEREDOC and expect expect to see that literal string it actually sees:
puts (buffer)
because the shell has removed the quotes and expanded the $expect_out variable for you.

Named groups from regular expression in case statement [duplicate]

I want to parse user input using named captures for readability.
When they type a command I want to capture some params and pass them. I'm using RegExps in a case statement and thus I can't assign the return of /pattern/.named_captures.
Here is what I would like to be able to do (for example):
while command != "quit"
print "Command: "
command = gets.chomp
case command
when /load (?<filename>\w+)/
load(filename)
end
end
named captures set local variables when this syntax.
regex-literal =~ string
Dosen't set in other syntax. # See rdoc(re.c)
regex-variable =~ string
string =~ regex
regex.match(string)
case string
when regex
else
end
I like named captures too, but I don't like this behavior.
Now, we have to use $~ in case syntax.
case string
when /(?<name>.)/
$~[:name]
else
end
This is ugly but works for me in Ruby 1.9.3:
while command != "quit"
print "Command: "
command = gets.chomp
case command
when /load (?<filename>\w+)/
load($~[:filename])
end
end
Alternatively you can use the English extension of $~, $LAST_MATCH_INFO.

Error converting a bash function to a csh alias

I am writing a csh alias so that I can use the following bash function in my csh :
function up( )
{
LIMIT=$1
P=$PWD
for ((i=1; i <= LIMIT; i++))
do
P=$P/..
done
cd $P
export MPWD=$P
}
(I stole the above bash function from here)
I have written this:
alias up 'set LIMIT=$1; set P=$PWD; set counter = LIMIT; while[counter!=0] set counter = counter-1; P=$P/.. ; end cd $P; setenv MPWD=$P'
However, I am getting the following error:
while[counter!=0]: No match.
P=/net/devstorage/home/rghosh/..: Command not found.
end: Too many arguments.
and my script is not working as intended. I have been reading up on csh from here.
I am not an expert in csh and what I have written above is my first csh script. Please let me know what I am doing wrong.
You can also do this
alias up 'cd `yes ".." | head -n\!* | tr "\n" "\/"`'
yes ".." will repeat the string .. indefinitely; head will truncate it to the number passed as argument while calling the alias ( !* expands to the arguments passed; similar to $# ) and tr will convert the newlines to /.
radical7's answer seems to be more neat; but will only work for tcsh ( exactly wat you wanted ). This should work irrespective of the shell
You can use the csh's repeat function
alias up 'cd `pwd``repeat \!^ echo -n /..`'
No loops needed (which is handy, because while constructs in tcsh seem very finicky)
For multiple lines of code, aliases must be within single quotes, and each end of line must precede a backslash. The end of the last line must precede a single quote to delimit the end of the alias:
alias up 'set counter = $1\
set p = $cwd\
while $counter != 0\
# counter = $counter - 1\
set p = $p/..\
end\
cd $p\
setenv mpwd $p'
By the way, variables set with set are better with the equal sign separated from the variable name and content; setenv doesn't require an equal sign; math functionality is provided by #; control structures make use of parentheses (though aren't required for simple tests); use $cwd to print the current working directory.

Using Named Captures with regex match in Ruby's case...when?

I want to parse user input using named captures for readability.
When they type a command I want to capture some params and pass them. I'm using RegExps in a case statement and thus I can't assign the return of /pattern/.named_captures.
Here is what I would like to be able to do (for example):
while command != "quit"
print "Command: "
command = gets.chomp
case command
when /load (?<filename>\w+)/
load(filename)
end
end
named captures set local variables when this syntax.
regex-literal =~ string
Dosen't set in other syntax. # See rdoc(re.c)
regex-variable =~ string
string =~ regex
regex.match(string)
case string
when regex
else
end
I like named captures too, but I don't like this behavior.
Now, we have to use $~ in case syntax.
case string
when /(?<name>.)/
$~[:name]
else
end
This is ugly but works for me in Ruby 1.9.3:
while command != "quit"
print "Command: "
command = gets.chomp
case command
when /load (?<filename>\w+)/
load($~[:filename])
end
end
Alternatively you can use the English extension of $~, $LAST_MATCH_INFO.

Resources