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 = <FP>;

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;
    }

}

···

--
Posted via http://www.ruby-forum.com/.

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

···

--
Posted via http://www.ruby-forum.com/.

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?

···

--
Posted via http://www.ruby-forum.com/.

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

···

--
Posted via http://www.ruby-forum.com/.

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

Why did Ruby1.8.6 not support this syntax?

···

--
Posted via http://www.ruby-forum.com/.

I can easily create a perl script like below:

########### my test.pl
use strict;
use warnings;

open FP, "demo.txt";

my @lines = <FP>;

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;
    }

}

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

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:
<quote> f.puts if y.size==0 </quote>
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:

···

--
Posted via http://www.ruby-forum.com/.

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.

···

On Fri, Oct 4, 2013 at 6:04 PM, Dave Hwong <lists@ruby-forum.com> wrote:

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

Why did Ruby1.8.6 not support this syntax?

--
Posted via http://www.ruby-forum.com/\.

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:

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

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

···

On Sat, Oct 5, 2013 at 4:32 PM, Harry Kakueki <list.push@gmail.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

> 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

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 7:26 AM, Dave Hwong <lists@ruby-forum.com> 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:
<quote> f.puts if y.size==0 </quote>
Are you going to print a new line?

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

···

On Sat, Oct 5, 2013 at 5:39 PM, Harry Kakueki <list.push@gmail.com> 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:

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.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

>

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 9:06 PM, Robert Klemme <shortcutter@googlemail.com>wrote:

On Sat, Oct 5, 2013 at 5:39 PM, Harry Kakueki <list.push@gmail.com> wrote:

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 Sun, Oct 6, 2013 at 3:35 PM, Harry Kakueki <list.push@gmail.com> wrote:

On Sun, Oct 6, 2013 at 9:06 PM, Robert Klemme <shortcutter@googlemail.com> > wrote:

On Sat, Oct 5, 2013 at 5:39 PM, Harry Kakueki <list.push@gmail.com> 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.

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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

Apology accepted.
Let's get back to Ruby.

Harry