Help to script Text processing in Ruby for quick learning to newbie

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;

####### demo.txt
BLOCK ENGINE;
DATA: 31 – 16;
ADDR: 15 – 0 ;
LENGTH: 31 – 0;
WIDTH: 60 – 0;
THICKNESS: 2 – 1;
FUSE: NO;
SWITCH : DISABLED;
ENDBLOCK

######### 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

Thanks Joel for your quick reply.

I try to run your script but it failed with below msg:
$>ruby test01.rb

t01.rb:1:in `foreach’: no block given (LocalJumpError)
from t01.rb:1

I am using Ruby in ruby 1.8.6 (2007-09-24 patchlevel 111)
[i386-mswin32]. Is there anything wrong?

Okay, when I moved to Ruby1.9.x the issue disappeared.

Why did Ruby1.8.6 not support this syntax?

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.

I guess something wrong with my Ruby installation.
It does not support File.foreach() somehow. Can anyone have better idea?

elsif ($line =~ m/(\w+)\s*:\s*(\w+)/) {

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

Harry

Here is a way to keep the regular expression more readable (for me,
anyway).

Uh, your brain must have quite different wiring than mine. :slight_smile:

I’m sure it does. Thank you. :slight_smile:

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.

Harry

On Sat, Oct 5, 2013 at 4:32 PM, Harry K. [email protected]
wrote:

Here is a way to keep the regular expression more readable (for me, anyway).

Uh, your brain must have quite different wiring than mine. :slight_smile:

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

Kind regards

robert

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. :slight_smile:

On Sun, Oct 6, 2013 at 7:26 AM, Dave H. [email protected] wrote:

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.

Harry

On Sun, Oct 6, 2013 at 9:06 PM, Robert K.
[email protected]wrote:

On Sat, Oct 5, 2013 at 5:39 PM, Harry K. [email protected] wrote:

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.

See any difference? I did.

Harry

On Sun, Oct 6, 2013 at 3:35 PM, Harry K. [email protected]
wrote:

“You forgot to close the file.”

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.

Kind regards

robert

On Sat, Oct 5, 2013 at 5:39 PM, Harry K. [email protected]
wrote:

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.

Cheers

robert

robert

Apology accepted.
Let’s get back to Ruby.

Harry