scanning strings, backward?

B

Bil Kleb

Hi,

I would like to automate a code cleanup task which involves
finding warning messages like,

Warning: ../../LibF90/bc_inviscid.f90, line 1707:
DT explicitly imported into BC_INVISCID_FLUX but not used
detected at BC_INVISCID_FLUX@<end-of-statement>

and removing the offending unused import.

So, the tasks are roughly,

1) Goto line 1707 of the file
2) Search backward until line.match /\Wdt\W/i
3) Remove /dt/i

I'm stuck on an elegant, i.e., Ruby, way to do the first
two steps. Please point me toward the glittering light.

Thanks,
 
V

Vidar Hokstad

Bil said:
So, the tasks are roughly,

1) Goto line 1707 of the file
2) Search backward until line.match /\Wdt\W/i
3) Remove /dt/i

I'm stuck on an elegant, i.e., Ruby, way to do the first
two steps. Please point me toward the glittering light.

For 1) Assuming the lines aren't fixed length: Read in the entire file
into an array (using IO#readlines), in which case you can skip straight
to the line you want, or counting line by line until you find the one
you want.

For 2) Any particular reason why you need to search backwards? My
suggestion would be to look at String#gsub - that will help you handle
both 2) and 3) in one go.

Vidar
 
M

M. Edward (Ed) Borasky

Vidar said:
For 1) Assuming the lines aren't fixed length: Read in the entire file
into an array (using IO#readlines), in which case you can skip straight
to the line you want, or counting line by line until you find the one
you want.

For 2) Any particular reason why you need to search backwards? My
suggestion would be to look at String#gsub - that will help you handle
both 2) and 3) in one go.

Vidar
For 2, can't you reverse the line and search forwards?
 
M

M. Edward (Ed) Borasky

Bil said:
Hi,

I would like to automate a code cleanup task which involves
finding warning messages like,

Warning: ../../LibF90/bc_inviscid.f90, line 1707:
DT explicitly imported into BC_INVISCID_FLUX but not used
detected at BC_INVISCID_FLUX@<end-of-statement>

and removing the offending unused import.

So, the tasks are roughly,

1) Goto line 1707 of the file
2) Search backward until line.match /\Wdt\W/i
3) Remove /dt/i

I'm stuck on an elegant, i.e., Ruby, way to do the first
two steps. Please point me toward the glittering light.

Thanks,

Wait a minute ... is the file you're editing always a Fortran source?
Why not just comment out the offending line rather than removing it?
Otherwise, removing a line changes the position number of every line
following it.
 
B

Bil Kleb

M. Edward (Ed) Borasky said:
Wait a minute ... is the file you're editing always a Fortran source?
Yes.

Why not just comment out the offending line rather than removing it?

Actually I was just going to remove the offending piece
from the line, e.g.,

use timestep, only : dt, dtau, n_time

would become,

use timestep, only : dtau, n_time

if 'dt' was the unused import.

Regards,
 
B

Bil Kleb

Vidar said:
For 2) Any particular reason why you need to search backwards? My
suggestion would be to look at String#gsub - that will help you handle
both 2) and 3) in one go.

The problem is I only want to replace only
the first occurrence before line 1707.

But, by reversing the lines per Ed B's suggestion,
I should be able to use String#sub on a temporary
buffer, and glue things back together for the
next item / line number combination? (not sounding
terribly elegant)

Later,
 
M

Morton Goldberg

For 1) Assuming the lines aren't fixed length: Read in the entire file
into an array (using IO#readlines), in which case you can skip
straight
to the line you want, or counting line by line until you find the one
you want.

For 2) Any particular reason why you need to search backwards? My
suggestion would be to look at String#gsub - that will help you handle
both 2) and 3) in one go.

I like this idea, but I would suggest using a hash rather than an
array. Hash the lines keyed to their line number. Then you can search
any which way you like.

Regards, Morton
 
V

Vidar Hokstad

Morton said:
I like this idea, but I would suggest using a hash rather than an
array. Hash the lines keyed to their line number. Then you can search
any which way you like.

I don't see what this would give you. An array of the lines in the
order read would be keyed to the line number. Assuming the Ruby array
implementation is sane using an array should be faster, and also has
the advantage that IO#readlines does all the work of reading the lines
in from file and returning a ready populated array.

Vidar
 
B

Bil Kleb

Bil said:
So, the tasks are roughly,

I should have just posted a test? Warning: untested test ;)

require 'import_cleaner'
require 'test/unit'

def class TestImportCleaner < Test::Unit::TestCase
def test_simple_case
compiler_output =<<-EOS
Warning: code.f90, line 8:
DT explicitly imported into SAY_TIME but not used
detected at SAY_TIME@<end-of-statement>
EOS
fortran_code =<<-EOC
subroutine print_dt
use timestep, only: dt
print*, dt
end
subroutine say_time
use timestep, only: dt, time
print *, 'Time: ', time
end
EOC
clean_code = fortran_code.clean_imports(compiler_output)
assert_match /only: time$/, clean_code, 'did not remove extraneous import'
assert_match /only: dt$/, clean_code, 'removed wrong import'
assert_match /print\*, dt/, clean_code, 'modified other code'
end
end

Regards,
 
V

Vidar Hokstad

Bil said:
The problem is I only want to replace only
the first occurrence before line 1707.

If you use IO#readlines you're working on an array of lines one by one.
So you'd do something
like this:

data = IO::readlines("test.txt")

data_to_replace.each do |r|
(0..(r[:lineno]-1)).times { |i| data[lineno].gsub!(r[:pattern],"") }
end

Assuming "data_to_replace" contains an array of arrays each containing
:lineno => line number to stop at, and :pattern contains the pattern to
delete. If the pattern can occur multiple times per line you need to do
slightly more work, but gsub!() can take a block so you have full
control over what you do with the matches.

Vidar
 
E

Eero Saynatkari

--opJtzjQTFsWo+cga
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,
=20
I would like to automate a code cleanup task which involves
finding warning messages like,
=20
Warning: ../../LibF90/bc_inviscid.f90, line 1707:
DT explicitly imported into BC_INVISCID_FLUX but not used
detected at BC_INVISCID_FLUX@<end-of-statement>
=20
and removing the offending unused import.
=20
So, the tasks are roughly,
=20
1) Goto line 1707 of the file

File.readlines for reasonably sized files, f.each_with_index
for skipping over until 1707.
2) Search backward until line.match /\Wdt\W/i
3) Remove /dt/i

Combine these by anchoring.

line.sub /(.*\W)dt(\W.*)$/i, '\1\2'

If the \W are spaces, strip one of them out.

--opJtzjQTFsWo+cga
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (FreeBSD)

iD8DBQFFLSxu7Nh7RM4TrhIRAup3AKC0YZ1ja+tdjRJHnWFvIIbMw+u6rQCZAdJh
EI8y0gWu7rZU+EYOP8mopQQ=
=woQX
-----END PGP SIGNATURE-----

--opJtzjQTFsWo+cga--
 
M

Morton Goldberg

I don't see what this would give you. An array of the lines in the
order read would be keyed to the line number. Assuming the Ruby array
implementation is sane using an array should be faster, and also has
the advantage that IO#readlines does all the work of reading the lines
in from file and returning a ready populated array.

It's a worthless idea. Somedays my brain behaves like a fried egg
even through I don't do drugs. Today seems to be one of those days
<sigh>.

Regards, Morton
 
R

Rick DeNatale

File.readlines for reasonably sized files, f.each_with_index
for skipping over until 1707.


Combine these by anchoring.

line.sub /(.*\W)dt(\W.*)$/i, '\1\2'

If the \W are spaces, strip one of them out.

I believe that the OP doesn't want to search line 1707 backwards for
dt, he want's to search the file backwards starting at line 1707 (or
maybe 1706) for a line containing dt.
 
E

Eero Saynatkari

--I3tAPq1Rm2pUxvsp
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

=20
I believe that the OP doesn't want to search line 1707 backwards for
dt, he want's to search the file backwards starting at line 1707 (or
maybe 1706) for a line containing dt.

Ah! /m :D

Granted in that case it would be simplest to use #rindex or to reverse
the String altogether.=20

--I3tAPq1Rm2pUxvsp
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (FreeBSD)

iD8DBQFFLml97Nh7RM4TrhIRAhNwAJ0SjNn7qwAf0VqR+ttBJdBDm+A4fQCdGi3j
4JDK2TnHwnppnxCouQdSHp4=
=2yCJ
-----END PGP SIGNATURE-----

--I3tAPq1Rm2pUxvsp--
 
B

Bil Kleb

Rick said:
I believe that the OP doesn't want to search line 1707 backwards for
dt, he want's to search the file backwards starting at line 1707 (or
maybe 1706) for a line containing dt.

Correct. Sorry for the confusion.

Regards,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top