How do I read a file in Ruby using a specific script? - ruby

I am doing a series of tutorials on how to code in Ruby. I want to read a .txt file using this formula:
filename = ARGV.first
prompt = "> "
txt = File.open(filename)
puts "Here's your file: #{filename}"
puts txt.read()
puts "I'll also ask you to type it again:"
print prompt
file_again = STDIN.gets.chomp()
txt_again = File.open(file_again)
puts txt_again.read()
The text file reads:
This is stuff I typed into a file. It is really cool stuff.
Lots and lots of fun to have in here.
The name for the text file is ex15_sample.txt. I tried with the above formula, and nothing seems to work. I have a hard understanding how to use both ARGV and STDIN.gets.chomp.
What should I do? I ask that you use the formula above; this stuff is a little confusing, so for now, just use the formula above.

The script works. You're not explaining how you're trying to run the script or what errors you're seeing, so it's a bit hard to help you.
If you have a text file named ex15_sample.txt in the same directory as your script (let's call it script.rb), and if you have Ruby set up properly, then if you run it with
$ ruby script.rb ex15_sample.txt
everything should work fine.
If you're trying to change the first line to always use ex15_sample.txt, be sure to put it in quotes:
filename = "ex15_sample.txt" # Without the quotes, you'll get an error.
Again, it's hard to help you without knowing exactly how you're running the script or what errors you're getting.
Update: I seems your issue is that you aren't clear on how to run a Ruby script. The simplest way is to, at your system's command prompt, type ruby then a space, then the name of the file with a Ruby script in it. If your script is in a file named script.rb, you would type ruby script.rb. That won't work if your script is in a file with a different name. If the script is in a file named read-a-file.rb, then you need to type ruby read-a-file.rb.
This particular script wants a command line argument after the file name. If the text file you want to read is in a file named ex15_sample.txt, then you need to type that after the script name. In the previous example, the command would become ruby read-a-file.rb ex15_sample.txt. That will only work if the files are in the same directory (a.k.a. folder).

Related

Permission Denied when passing files to a ruby program

I have a ruby program that accepts files as input. I am trying to test that this functionality works by piping a file into the program by entering
cat file1.txt | ./app.rb
However, when I do this I get -bash: ./app.rb: Permission denied
I have tried using sudo cat file1.txt | ./app.rb which prompts me for my password and then it appears nothing happens.
This works fine when I instead type
ruby app.rb file1.txt
Does anyone have any tips for how to get this to work?
As pointed out in the comments, I need to be able to read a file path from stdin AND pass them as parameters:
In my code I have this:
def input
if ARGV.length.positive?
ARGV
else
gets.chomp.split(' ')
end
end
I expect input to return an array of file paths.
As mentioned in the comments above, sending the contents of a file as STDIN to a program and passing the filename as a parameter are two very different things.
I cannot say which, if either, is "right" or "wrong" without knowing more context of what it is you're actually trying to achieve, but it's important to recognise the difference.
Now, the actual cause of the error here is that you're trying to execute the ruby file directly. You can fix this by running ruby on the filename instead:
cat file1.txt | ruby app.rb
It is possible to execute the file without writing ruby, but you must first make it executable:
chmod +x app.rb
And also write a Shebang at the top of the file, to specify that it should be executed as a ruby script, not a bash script (which is the default):
#!/usr/bin/env ruby

Ruby: Keep console open after script execution

I wrote a Ruby script like the following example. The basic functionality is the same:
# get input from the user
input = gets.chomp
# do awesome stuf with this input and print the response
puts do_awesome_stuff(input)
The problem is when I run the script it prints the solution I want, but the console window closes right after. I want the console to keep open.
I'm currently on windows, but the solution should be working on every system.
One way is to run the ruby script with a .bat file and pause it, like so:
ruby script.rb
PAUSE
I hope there is a way without the additional .bat file. Does Ruby has a function like PASUE integrated?
It seems like you double click the ruby script file.
Instead issue the following command in cmd shell.
ruby filename.rb
If you don't want that, you can add gets to the end of the script.
# get input from the user
input = gets.chomp
# do awesome stuf with this input and print the response
puts do_awesome_stuff(input)
gets # <----
But this is not recommended because .. if you run the command in cmd shell or terminal you should type extra Enter to return to the shell.
Use the -r options of irb.
irb -r ./filename.rb

Ruby - How to use -r switch with ruby command line tool

I was trying to figure out how to work the command line switch -r.
My understanding is that the code is typed out as follows:
ruby -r*nameOfRequired*
I am finding that this is not the case. When I type out the above and press enter, the terminal expects an "end of input syntax" and does not continue.
What am I missing? Does there need to be a space in between the switch and the name of the required file?
Please and thank you!
EDIT:
I am currently reading "The Well Grounded Rubyist" by David A. Black, and I came up with this question while reading the section on command line switches.
Having said that, I created a "test.rb" file, containing:
puts Date.today
Then, in the terminal, I typed out:
ruby -r date
I thought this would 'require' the date module, and then enable me to run the "test.rb" file, using ruby test.rb (given that I am in the correct directory).
Instead, the terminal cursor moves to a newline, expecting more input. Let me know if I need to clarify anything else. Thanks!
If you just type ruby -rmodule, then Ruby will load the module and wait for you to type the main program that requires that module.
If you just want to run the module and do nothing else, you can do do rubyfull-path-to-module without the -r, or ruby -rmodule -e exit, or ruby -rmodule </dev/null, or similar.
In general, the ruby command does not record any state from one run to the next, so you need to tell it every thing that it needs to know whenever you run it.
Whenever you run it, you need to tell it the main program to run or else it will expect you to type that program on the standard input. The -r does not specify the main program.
Try this:
ruby -rdate test.rb
According to ruby -h:
-rlibrary require the library, before executing your script
Without giving your script file path, it read the script from stdin.
Try following (You can omit script file path when you give -e command):
ruby -r**nameOfRequired** -e ""

Create an applescript from a perl and a ruby script?

I download protein sequences from http://ncbi.nlm.nih.gov/genomes/FLU/Database/nph-select.cgi#mainform, which are downloaded with filename FASTA.FA. For each protein in the file, it includes one describing row, and then protein sequence separated with a new row after each 70 characters.
Example:
>CAA47401 B/Yamagata/16/88 1988// NA
MLPSTIQTLTLFLTSGGVLLSLYVSASLSYLLYSDILLKFSPTEITAPKVPLDCANASNVQAVNRSATKG
MTLLLSEPEWTYPRLSCQGSTFQKALLISPHRFGESRGNSAPLIIREPFIACGPKECKHFALTHYAAQPG
>AAB26739 Influenza B virus 1973// NA
MLPSTIQTLTLFLTSGGVLLSLYVSASLSYLLYSDILLKFSPTKITAPTMSLDCANVSNVQAVNRSATKE
DVPCIGIEMVHDGGKETWHSAATAIYCLMGSGQLLWDIVTGVAMAL
I have a ruby script that converts this to a file that fits Excel better, where the first line gets one cell and the entire protein sequence gets one another cell (perl makes a tab between and Excel puts stuff separated with tab in a new cell).
This is my script:
ruby -e 'first_line = true; while line = STDIN.gets; line.chomp!;
if line =~ /^>/; puts unless first_line; print line[1..-1]; print "\t";
else; print line; end; first_line = false; end; puts' < ~/Downloads/FASTA.fa > ~/Downloads/Sequences.xls
On the website where I download the files you can change how the first line should be formatted, and I include a "+" between each description, and I then have a perl script that converts + to tab (some descriptions have a space within it, so I cant use space as a separator).
perl -p -i -e "s/\+/\t/g" ~/Downloads/Sequences.xls
These two hacks successfully creates a nice excel file for me, and I have made an Automator program from these two scripts that sits in my dock.
However, now my group wants me to create an applescript out of this. If I have understood this correctly, it's not as simple as just typing "do shell script" and then paste the script, but you have to format the actual script itself so that applescript understands it. Could anyone please help me in creating this?
Thanks!
I'd say you should make the ruby script into a proper .rb file, and while you're at it, use Ruby to do the tab-replacement (or use the Spreadsheet gem, if you want fancier Excel output, though that might require some setup on other people's computers). Or do it all in Perl instead. Just to save you the trouble of spinning up two runtimes for such trivial search/replace stuff. For that matter you can do it all in sed, I'm sure.
Anyway, once you have the script as a file, you can make a new script in AppleScript Editor and save it as a script bundle. Then you can include the scripts "inside" your AppleScript. That way, you know where the scripts are, and they're much, much easier to edit if need be. Then you can use do shell script to invoke the script with the proper arguments. Simplified example:
-- get script path
set rb to POSIX path of (path to me) & "Contents/Resources/Scripts/convert.rb"
-- run script
do shell script "ruby '" & rb & "' < inputfile.fa > outputfile.xls"
If you want, you can even get some drag-and-drop conversion going, instead of hard-coding a path to ~/Downloads/FASTA.fa (if someone forgets to move/delete an old download, it'll keep converting that one, and writing over the same xls, since a new download would be "FASTA-1.fa" or something, so avoid hard-coded paths if you can)

Python Windows7: Odd behaviour opening file for append

I am seeing odd behaviour when I open a file in append mode ('a+') under Windows 7 using Python.
I was wondering whether the behaviour is in fact incorrect or I am misunderstanding how to use the following code:
log_file= open(log_file_path, "a+")
return_code = subprocess.call(["make", target], stdout=log_file, stderr=subprocess.STDOUT)
log_file.close()
The above code lines does not properly append to the file. In fact on subsequent runs it won't even modify the file.
I tested it out using the Python Shell as well.
Once the file has been opened for the first time, making multiple subprocess calls will append properly to the file, however once the file has been closed and reopened it will never append again.
Anyone have any clues?
Thanks
To further simply the problem Here is another set of steps that will fail:
log_file=open("temp.txt", "a+")
log_file.write("THIS IS A TEST")
log_file.close()
log_file=open("temp.txt", "a+")
subprocess.call(["echo", "test"], stdout=log_file, stderr=subprocess.STDOUT, shell=True)
log_file.close()
If you open the file temp.txt here is what I see:
testS A MUTHER F** TEST
It looks like your problem is in the use of shell=True. From Python documentation for POpen:
On Unix, with shell=True: If args is a string, it specifies the
command string to execute through the shell. This means that the
string must be formatted exactly as it would be when typed at the
shell prompt. This includes, for example, quoting or backslash
escaping filenames with spaces in them. If args is a sequence, the
first item specifies the command string, and any additional items will
be treated as additional arguments to the shell itself.
So it looks like "echo" is the command, and "test" gets sent as an argument to the shell, instead of to "echo".
So changing your subprocess call to either:
subprocess.call("echo test", stdout=log_file, stderr=subprocess.STDOUT, shell=True)
or:
subprocess.call(["echo", "test"], stdout=log_file, stderr=subprocess.STDOUT)
Fixes the problem, at least in my testing.
see http://mail.python.org/pipermail/python-list/2009-October/1221841.html
briefly: opening a file in append mode leaves the file ptr in an implementation-dependent state. seek to the end to get the same results on windows as on linux.

Resources