Ruby script to read output from alias - ruby-on-rails

I have setup an alias in /etc/aliases so that each time an email comes in to a specific address, the text of the email is sent to a Ruby script. Like so:
example: |/etc/smrsh/my_script.rb
I need to know how to read the piped data in my Ruby script..
I have written a simple Perl script that can read the data.. just can't figure out how to do it in Ruby.
Here is the relevant lines in the Perl script:
my $fout = "/tmp/email.out";
open( EM, ">$fout" );
while( <> ) {
chomp;
print EM "$_\n";
}

You can use STDIN to read your pided data. The equivalent of your Perl code would be something like:
out = File.open("/tmp/email.out", "a+")
STDIN.each do |line|
out.puts line
end

Related

Using io.tmpfile() with shell command, ran via io.popen, in Lua?

I'm using Lua in Scite on Windows, but hopefully this is a general Lua question.
Let's say I want to write a temporary string content to a temporary file in Lua - which I want to be eventually read by another program, - and I tried using io.tmpfile():
mytmpfile = assert( io.tmpfile() )
mytmpfile:write( MYTMPTEXT )
mytmpfile:seek("set", 0) -- back to start
print("mytmpfile" .. mytmpfile .. "<<<")
mytmpfile:close()
I like io.tmpfile() because it is noted in https://www.lua.org/pil/21.3.html :
The tmpfile function returns a handle for a temporary file, open in read/write mode. That file is automatically removed (deleted) when your program ends.
However, when I try to print mytmpfile, I get:
C:\Users\ME/sciteLuaFunctions.lua:956: attempt to concatenate a FILE* value (global 'mytmpfile')
>Lua: error occurred while processing command
I got the explanation for that here Re: path for io.tmpfile() ?:
how do I get the path used to generate the temp file created by io.tmpfile()
You can't. The whole point of tmpfile is to give you a file handle without
giving you the file name to avoid race conditions.
And indeed, on some OSes, the file has no name.
So, it will not be possible for me to use the filename of the tmpfile in a command line that should be ran by the OS, as in:
f = io.popen("python myprog.py " .. mytmpfile)
So my questions are:
Would it be somehow possible to specify this tmpfile file handle as the input argument for the externally ran program/script, say in io.popen - instead of using the (non-existing) tmpfile filename?
If above is not possible, what is the next best option (in terms of not having to maintain it, i.e. not having to remember to delete the file) for opening a temporary file in Lua?
You can get a temp filename with os.tmpname.
local n = os.tmpname()
local f = io.open(n, 'w+b')
f:write(....)
f:close()
os.remove(n)
If your purpose is sending some data to a python script, you can also use 'w' mode in popen.
--lua
local f = io.popen(prog, 'w')
f:write(....)
#python
import sys
data = sys.stdin.readline()

Why the lua function io.write() did not work. It only display the results on the terminal, rather than writing to a file

I am learning the Lua IO library. I'm having trouble with io.write(). In Programming Design in Lua, there is a piece of code that iterates through the file line by line and precedes each line with a serial number.
This is the file I`m working on:
test file: "iotest.txt"
This is my code
io.input("iotest.txt")
-- io.output("iotest.txt")
local count = 0
for line in io.lines() do
count=count+1
io.write(string.format("%6d ",count), line, "\n")
end
This is the result of the terminal display, but this result cannot be written to the file, whether I add IO. Output (" iotest.txt ") or not.
the results in terminal
This is the result of file, we can see there is no change
The result after code running
Just add io.flush() after your write operations to save the data to the file.
io.input("iotest.txt")
io.output("iotestout.txt")
local count = 0
for line in io.lines() do
count=count+1
io.write(string.format("%6d ",count), line, "\n")
end
io.flush()
io.close()
Refer to Lua 5.4 Reference Manual : 6.8 - Input and Output Facilities
io.flush() will save any written data to the output file which you set with io.output
See koyaanisqatsi's answer for the optional use of file handles. This becomes especially useful if you're working on multiple files at a time and gives you more control on how to interact with the file.
That said you should also have different files for input and output. You'll agree that it doesn't make sense to read and write from and to the same file alternatingly.
For writing to a file you need a file handle.
This handle comes from: io.open()
See: https://www.lua.org/manual/5.4/manual.html#6.8
A file handle has methods that acts on self.
Thats the function after the : at file handle.
So io.write() puts out on stdout and file:write() in a file.
Example function that can dump a defined function to a file...
fdump=function(func,path)
assert(type(func)=="function")
assert(type(path)=="string")
-- Get the file handle (file)
local file,err = io.open(path, "wb")
assert(file, err)
local chunk = string.dump(func,true)
file:write(chunk)
file:flush()
file:close()
return 'DONE'
end
Here are the methods, taken from io.stdin
close = function: 0x566032b0
seek = function: 0x566045f0
flush = function: 0x56603d10
setvbuf = function: 0x56604240
write = function: 0x56603e70
lines = function: 0x566040c0
read = function: 0x56603c90
This makes it able to use it directly like...
( Lua console: lua -i )
> do io.stdout:write('Input: ') local result=io.stdin:read() return result end
Input: d
d
You are trying to open the same file for reading and writing at the same time. You cannot do that.
There are two possible solutions:
Read from file X, iterate through it and write the result to another file Y.
Read the complete file X into memory, close file X, then delete file X, open the same filename for writing and write to it while iterating through the original file (in memory).
Otherwise, your approach is correct although file operations in Lua are more often done using io.open() and file handles instead of io.write() and io.read().

Need to collect only emails using Ruby code

I've received a list of emails that I'd like to run an email campaign on, however, in the list there are some URL's... and it complicates things.
Here's the standard formatting of the email address, for example:
news#ydr.com
I'd like to paste the list in terminal and run a command to ONLY capture all of the email addresses and save them to a file and remove any URLS.
Please advise! It is much appreciated :)
If you are just looking to catch most emails this regex might work.
I got this regex from here How to validate an email address using a regular expression?
They talk about the much more complicated RFC822 email regex
#!/usr/bin/env ruby
input = $stdin.readlines # ctrl + D after paste
input.each do |f|
puts f if f[/^[a-zA-Z0-9_.+\-]+#[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$/]
end
# test input
# foo#bar.com
# www.cnn.com
# test.email#go.com
# turdburgler#mcdo.net
# http://www.google.com
To write emails to a file:
#!/usr/bin/env ruby
file = File.open("emails.txt", "w")
input = $stdin.readlines # ctrl + D after paste
input.each do |f|
file.write(f) if f[/^[a-zA-Z0-9_.+\-]+#[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$/]
end
file.close
Just to be clear, this is a ruby script which should be ran like this.
Save the script as a file, ie email_parser.rb.
chmod +x email_parser.rb
./email_parser.rb # this will wait for stdin, here you paste the list in to the terminal
When the terminal is hanging waiting, paste the list of emails in, then press ctrl + D to tell the program that this is the EOF. The program will then run through the list of emails/urls and parse. The output of this will be a file if using the updated script. The file will be in the same folder you ran the script and be called emails.txt

regexp matching in rails app

I have the following string that needs to be replaced by an empty character in rails. Followed many tutorials and docs. Please help me achieve this.
String:
/home/<someword>/dbdumps/backup.sql
To be replaced as:
backup
To get the file name from a path, I'd use File#basename
File.basename('/home/<someword>/dbdumps/backup.sql', '.sql')
#=> 'backup'
if "someword" is the only thing that changes you dont even need regex.
Assume
path = "/home/<someword>/dbdumps/backup.sql"
then
path.split("/").last.split(".").first
returns
=> "backup"
The easiest solution would be a gsub (string substitution) like so:
string = "home/<someword>/dbdumps/backup.sql"
new_string = string.gsub(%r{home/(.*)/dbdumps/backup.sql}, 'backup' )
This is a simple example of string substitution.
In a rails app i do a Net:SSH:start( ) and run ssh.exec!('ls /home//dbdumps/.sql'). I am ?sending the output to a string and then i have to display the list of the files. For that I am taking the output into a string and trying to do a gsub. Is this the right approach?
I would not consider it pretty (naive code, no error checking, loops with requests) but something like this could do the job for you. It depends if you want to end up with just the backup names or the full path.
ssh.exec!("ls -l /home/") do |channel, stream, data|
directories << data if stream == :stdout
end
directories.each do |dir|
ssh.exec!("ls -l /home/" + dir + "dbdumps") do |channel, stream, data|
backup_names << /home/" + dir + "/" + data if stream == :stdout
end
end
hope this helps

Reading a file line by line using bash, extracting some data. How?

I want to read a file a extract information from it based on certain tag. For example :
SCRIPT_NAME:mySimpleShell.sh
This is a simple shell. I would like to have this as
Description. I also want to create a txt file our of this.
SCRIPT_NAME:myComplexShell.sh
This is a complex shell. I would like to have this as
Description. I also want to create a txt file our of this.
So when I pass in this file to my shell script, my shell will read it line by line and
when it gets to SCRIPT_NAME, It extract it and save it in $FILE_NAME, then starts writing
the description to a file on disk with $FILE_NAME.txt name. And It does it until It reaches the end of file. If there is 3 SCRIPT_NAME tag, then it creates 3 description file.
Thanks for helping me in advance :)
Read the lines using a while loop. Use a regex to check if a line has SCRIPT_NAME and if so, extract the filename. This is shown below:
#! /bin/bash
while IFS= read -r line
do
if [[ $line =~ SCRIPT_NAME:(.*$) ]]
then
FILENAME="${BASH_REMATCH[1]}"
echo "Writing to $FILENAME.txt"
else
echo "$line" >> "$FILENAME.txt"
fi
done < inputFile
#!/bin/sh
awk '/^SCRIPT_NAME:/ { split( $0, a, ":" ); name=a[2]; next }
name { print > name ".txt" }' ${1?No input file specified}

Resources