Elegant way to rename a file with an user-supplied expression?

Hi.

I'm creating a small Ruby program to do some chores that I used to do with
different programs coupled together and shell scripts. I'm doing it mostly to
_learn_ more Ruby (I'm still a beginner), so if in the end I have to invoke a
foreign program in another process, I will, but I want to at least try other
possibilites.

I want to rename a file, and I would like to let the user supply the way to do
the rename as a string. There is a "rename" program that comes with Perl (at
least on some Linux distributions), and that is exactly like I would want to
do. The program is just 40 lines (http://pastie.org/9625733) and it simply
calls eval on the user-supplied string:

# Change from YYYYMMDD to YYYY-MM-DD
rename 's|(\d\d\d\d)(\d\d)(\d\d)|$1-$2-$3|' *.foo

How would you do something like that? I can use eval too, but I don't really
understand the second parameter, and documentation is scarce about eval. With
Perl here the eval()ed code is applied to the $_ automatic variable, so is
convenient. I don't know how to do such thing conveniently with Ruby.

I also though on how to do not just any expression, which is cool, but
unnecessary since 99% of the times a simple call to gsub would do fine. On that
vein, is there an elegant way to do what the example above? That is, supply
one string that contains both the match and the substitution. I understand it
as both Ruby and Perl having /regexp/ built into the language, but Perl even
having s/// as "first class" language construct.

To summarize:

1. How would you use eval to apply an user supplied string to transform a
single variable?
2. Is there a succint way to perform a substitution on a string like sed/Perl
do?

Thank you very much.

···

--
Alex (a.k.a. suy) | GPG ID 0x0B8B0BC2
http://barnacity.net/ | http://disperso.net

% ri Kernel.eval
= Kernel.eval

(from ruby core)

···

On Oct 6, 2014, at 12:50, Alejandro Exojo <suy@badopi.org> wrote:

documentation is scarce about eval

------------------------------------------------------------------------------
  eval(string [, binding [, filename [,lineno]]]) -> obj

------------------------------------------------------------------------------

Evaluates the Ruby expression(s) in string. If
binding is given, which must be a Binding object, the evaluation
is performed in its context. If the optional filename and
lineno parameters are present, they will be used when reporting
syntax errors.

  def get_binding(str)
    return binding
  end
  str = "hello"
  eval "str + ' Fred'" #=> "hello Fred"
  eval "str + ' Fred'", get_binding("bye") #=> "bye Fred"

The gsub part is easy enough:

2.0.0p195 :015 > s = "12345678"
=> "12345678"
2.0.0p195 :016 > r = "(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)"
=> "(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)"
2.0.0p195 :017 > p = "\\1-\\2-\\3"
=> "\\1-\\2-\\3"
2.0.0p195 :018 > s.gsub(re,p)
=> "1234-56-78"

The syntax is a bit different since the gsub replacement syntax is
different from perl's, but the idea is the same.

Jesus.

···

On Mon, Oct 6, 2014 at 9:50 PM, Alejandro Exojo <suy@badopi.org> wrote:

Hi.

I'm creating a small Ruby program to do some chores that I used to do with
different programs coupled together and shell scripts. I'm doing it mostly to
_learn_ more Ruby (I'm still a beginner), so if in the end I have to invoke a
foreign program in another process, I will, but I want to at least try other
possibilites.

I want to rename a file, and I would like to let the user supply the way to do
the rename as a string. There is a "rename" program that comes with Perl (at
least on some Linux distributions), and that is exactly like I would want to
do. The program is just 40 lines (http://pastie.org/9625733\) and it simply
calls eval on the user-supplied string:

# Change from YYYYMMDD to YYYY-MM-DD
rename 's|(\d\d\d\d)(\d\d)(\d\d)|$1-$2-$3|' *.foo

How would you do something like that? I can use eval too, but I don't really
understand the second parameter, and documentation is scarce about eval. With
Perl here the eval()ed code is applied to the $_ automatic variable, so is
convenient. I don't know how to do such thing conveniently with Ruby.

I also though on how to do not just any expression, which is cool, but
unnecessary since 99% of the times a simple call to gsub would do fine. On that
vein, is there an elegant way to do what the example above? That is, supply
one string that contains both the match and the substitution. I understand it
as both Ruby and Perl having /regexp/ built into the language, but Perl even
having s/// as "first class" language construct.

To summarize:

1. How would you use eval to apply an user supplied string to transform a
single variable?
2. Is there a succint way to perform a substitution on a string like sed/Perl
do?

That's exactly what I meant. That documentation points to Binding, which in
turn points to binding(). Is not necessarily an easy concepto to grasp,
specially if you are still beginning. I called that scarce. Maybe hard was a
better word, but I searched for non-trivial examples online I didn't found, so
that was my feeling.

···

El Monday 06 October 2014, Ryan Davis escribió:

On Oct 6, 2014, at 12:50, Alejandro Exojo <suy@badopi.org> wrote:
> documentation is scarce about eval

% ri Kernel.eval

--
Alex (a.k.a. suy) | GPG ID 0x0B8B0BC2
http://barnacity.net/ | http://disperso.net

The gsub part is easy enough:

(...)

The syntax is a bit different since the gsub replacement syntax is
different from perl's, but the idea is the same.

That's what I said, and is fine of course. I just wondered wheter it existed
another way to do it with one string only (the CLI interface was getting
complicated already). The most likely answer was "no" of course, but given
that the language has a first class regular expression, it might have a
substitution, too (like Perl or sed).

···

El Wednesday 08 October 2014, Jesús Gabriel y Galán escribió:

--
Alex (a.k.a. suy) | GPG ID 0x0B8B0BC2
http://barnacity.net/ | http://disperso.net