develooper Front page | perl.macperl.anyperl | Postings from March 2002

Re: [MacPerl-AnyPerl] -pi switches

Thread Previous | Thread Next
Bart Lateur
March 28, 2002 02:04
Re: [MacPerl-AnyPerl] -pi switches
Message ID:
On Thu, 28 Mar 2002 12:17:28 +0800, allan wrote:

>i need to detab a bunch of files in a bunch of directories.
>this script:
>#!/usr/bin/perl -pi
>s/\t/    /;
>will do what i want when a supply the files as arguments
>from the commandline.

Wow, hold it. If you use something that simple, you'll likely end up
with some weird looking text (source?) files.

You seem to want tab positions every 4 columns. Now, somebody will
likely suggest using some module for that, but here is some handcrafted

	s/(.*?)\t/$1.(' ' x (4-length($1)%4))/ge;

It will take into account the length of the string before the tab
starting from the start of the string, from the previous newline, or
from the last replaced tab; and pad with 1 to 4 spaces so the string
length becomes the next multiple of 4.

It seems to work fine for me.

>i have a script that traverse all directories from a
>specfied starting point.
>so when i recursively get to a new file i wish to detab that
>file on the fly as if i had supplied the filename as an argument
>sub recursion {
>  ...
>  if (-f $specfile ) {
>    # detab code goes here
>  }
>  ...
>  # next file/dir
>is that possible still using the -i switch?

My first thought would be to have two scripts, and call the other script

	system($^X, "-pi", "", $_);

$^X is the full path of the perl executable.

But, then, of course, your platform should support calling external perl
scripts this way. I think that this will be problematic on a Mac, most
of all if you don't have ToolServer installed (IIRC).

Also note that some platforms do require that you provide an extension
for the -i command line switch. (Windows, Mac ?) You'll get a backup
file that way, I know...

BTW instead of calling an external script, you ougth to be able to use
the -e command line option.
A second approach would be to have just one script, fill @ARGV in a
BEGIN block. Yeah, that looks like it would be the best approach.

	#!/usr/bin/perl -pi
	     use File::Find;
	     use Cwd;
	     my @argv = @ARGV; @ARGV = ();
	     find sub {
	         push @ARGV, $File::Find::name if -f and /\.txt$/;
	     }, @argv ? @argv : cwd;

	s/(.*?)\t/$1.(' ' x (4-length($1)%4))/ge;


The idea is that you pass the path of the root directory(/-ies) on the
command line, or it will pick the current working directory without
arguments. It will fill @ARGV with a complete list of all found files.
BTW any plain files in the command arguments get included too, if they
match the pattern. That's a feature of File::Find.

It does that in a BEGIN block, so this is run once, at the start of your
script. The main body of the script is run using the -pi command line
switches, so that part runs once for every line in the input files.


Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About