Hello, I am completely new to Ruby and want to start learning it in an
efficient way. Can anyone create a text processing Ruby script for me? I
attached a perl script that shows that way I did it.
I need a ruby script to convert demo.txt to out.txt;
######### out.txt
--------- ENGINE --------
the DATA width is 15 in decimal
the ADDR width is 15 in decimal
the LENG width is 31 in decimal
the WIDT width is 60 in decimal
the THIC width is 1 in decimal
the FUSE status is NO
the SWIT status is DISABLED
I can easily create a perl script like below:
########### my test.pl
use strict;
use warnings;
open FP, “demo.txt”;
my @lines = ;
foreach my $line(@lines) {
if ($line =~ m/\bBLOCK\s+(\w+)/) {
printf “--------- %s --------\n”, $1;
}
if ($line =~ m/(\w+)\s*:\s*(\d+) -- (\d+)/) {
my $w = substr ($1, 0, 4);
my $d = $2 - $3;
printf “the %-10s width is %-5d in decimal\n”, $w, $d;
}
elsif ($line =~ m/(\w+)\s*:\s*(\w+)/) {
my $w = substr ($1, 0, 4);
printf “the %-10s status is %-5s\n”, $w, $2;
}
I’ve pretty much left the Regexp alone, here’s my translation:
File.write( ‘out.txt’, File.foreach(‘demo.txt’).map do |line|
case line
when /\bBLOCK\s+(\w+)/
“--------- #{$1} --------”
when /(\w+)\s*:\s*(\d+) – (\d+)/
“the %-10s width is %-5d in decimal” % [ $1[0…3], $2.to_i -
$3.to_i ]
when /(\w+)\s*:\s*(\w+)/
“the %-10s status is %-5s” % [ $1[0…3], $2 ]
end
end.compact.join($/) )
Output:
--------- ENGINE --------
the DATA width is 15 in decimal
the ADDR width is 15 in decimal
the LENG width is 31 in decimal
the WIDT width is 60 in decimal
the THIC width is 1 in decimal
the FUSE status is NO
the SWIT status is DISABLED
You can add it to 1.8 simply by defining it. Ruby 1.8.5/6 was released
almost seven years ago. It was a much different language then. Some of
the
block scoping paradigms have changed. What’s a more interesting is why
later rubies don’t support legacy syntax as these “bugs” were fixed.
my $w = substr ($1, 0, 4);
printf “the %-10s status is %-5s\n”, $w, $2;
}
}
Here is a way to keep the regular expression more readable (for me,
anyway).
You may need some adjustments depending on your specs.
f = File.open("./out.txt",“w”)
File.open("./demo.txt",“r”).each do |x|
y = x.chomp.split(/BLOCK|:|–|;|END/)
f.puts “--------- #{y[1].lstrip} --------” if y.size==2 && y[0] == “”
f.puts “the #{y[0].lstrip[0…3]} width is
#{(y[1].to_i-y[2].to_i).to_s.ljust(2)} in decimal” if y.size==3
f.puts “the #{y[0].lstrip[0…3]} status is #{y[1].lstrip}” if
y.size==2 && y[0] != “”
f.puts if y.size==0
end
Here is a way to keep the regular expression more readable (for me,
anyway).
Uh, your brain must have quite different wiring than mine.
I’m sure it does. Thank you.
I’d probably have taken Joel’s solution with these small changes:
use ARGF so users can post arbitrary number of files on command line
output to stdout so user can decide where the output goes
You are not the one asking for a solution.
I just offered an idea to the OP and I indicated that he may want to
make
some changes.
What you want doesn’t matter.
Have a nice day.
Here is a way to keep the regular expression more readable (for me, anyway).
Uh, your brain must have quite different wiring than mine.
y.size==2 && y[0] != “”
f.puts if y.size==0
end
You could at least have closed file handles properly.
I’d probably have taken Joel’s solution with these small changes:
use ARGF so users can post arbitrary number of files on command line
output to stdout so user can decide where the output goes
ARGF.each_line do |line|
case line
when /\bBLOCK\s+(\w+)/
puts “--------- #$1 --------”
when /(\w+)\s*:\s*(\d+) – (\d+)/
printf “the %-10s width is %-5d in decimal\n”, $1[0, 4], $2.to_i -
$3.to_i
when /(\w+)\s*:\s*(\w+)/
printf “the %-10s status is %-5s\n”, $1[0, 4], $2
end
end
Thanks Harry, your solution is good for me. Your strategy is actually
convert the text into an array line by line, and then pick up what you
want to format. I learned much from your example.
Something that I don’t understand is why you need add:
f.puts if y.size==0
Are you going to print a new line?
Hello Robert, I like your recommended style; it will make the script
more reusable. As to output, I am OKAY to STDOUT or file_io, but this
might be my mistake which I showed in Perl with STDOUT but actually I
required file_io.
Thanks Harry, your solution is good for me. Your strategy is actually
convert the text into an array line by line, and then pick up what you
want to format. I learned much from your example.
Something that I don’t understand is why you need add:
f.puts if y.size==0
Are you going to print a new line?
That line is not necessary.
It just puts a space between ENDBLOCK and the beginning of another block
if
there is one.
Not important.
I sense there might be a misunderstanding: I did not intend to
depreciate anybody’s brain wiring. I just wanted to stress the
obvious. And similarly to you I offered a solution which is subject
to commenting by anyone - as anyone else’s is, too.
Maybe.
Maybe it is a cultural thing.
The brain wiring comment did not bother me.
Different does not mean bad.
The fact that you commented on my example did not bother me.
But,
“You forgot to close the file.”
You could at least have closed file handles properly.
You could at least have closed file handles properly.
See any difference? I did.
I didn’t as the offending quote was not included in your response.
But now I see where you’re coming from. Thank you for the
explanation! That is a bad way to put it. I am sorry.
I’d probably have taken Joel’s solution with these small changes:
use ARGF so users can post arbitrary number of files on command line
output to stdout so user can decide where the output goes
You are not the one asking for a solution.
I just offered an idea to the OP and I indicated that he may want to make
some changes.
What you want doesn’t matter.
Have a nice day.
I sense there might be a misunderstanding: I did not intend to
depreciate anybody’s brain wiring. I just wanted to stress the
obvious. And similarly to you I offered a solution which is subject
to commenting by anyone - as anyone else’s is, too.