LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-08-2006, 06:38 AM   #1
WindozBytes
Member
 
Registered: Aug 2001
Location: CT, USA
Distribution: Mandriva 2008
Posts: 105

Rep: Reputation: 15
perl: global replace using hash


The task at hand is to change string1 to string2 in a known list of source files. I've written the perl below to fetch string1 and string2 from a separate file and store them in a hash. The problem is that when I try to make the substitution, the hash values do not seem to match string1 from the source file. (I believe this is the problem since when I hard-code string1 and string2, I get the desired result.) Once changed, the text is written back to the original file, so editing in-place is certainly an option, but the process has to be scripted rather than invoked from a command line.

I've included the lc function when loading the hash, since I know at some point in the future, someone will use a capital letter in a key in the input file, but even without the lc function, the result is the same.

TIA for any assistance.
- - - - - - - - - - - - - - -

#!/usr/bin/perl

use strict ; # enforce good programming rules.
use Cwd ; # include module to allow retrieval of current working directory.


#-------------------------------------------------------------------------------------
# Print begin message.
# ====================

print "Beginning Software Distribution Process: " ; system "date +%Y%m%d-%T" ;
print "\n" ;


#-------------------------------------------------------------------------------------
# Set pkg_name variable.
# ======================

my $dir = getcwd; # get current working directory.
my @dir = split /\//, $dir ; # split full path into directory names and load into array.
$_ = @dir[$#dir] ; # set default variable ( $_ ) to last element of directory array.
s/.tmp$// ; # remove .tmp from default variable.
my $pkg_name = $_ ; # store resulting package name.

print "Package name set to: $pkg_name\n" ;
print "\n" ;


#-------------------------------------------------------------------------------------
# Set directory variables.
# ========================

my $PKG_HOME = $dir ;
print "Package home set to: $PKG_HOME\n" ;
print "\n" ;

#-------------------------------------------------------------------------------------
# Set file variables.
# ===================

my $location = "$PKG_HOME/path.logon" ;
my $file_lst = "$PKG_HOME/objects.lst" ;

#-------------------------------------------------------------------------------------
# Create global variables.
# ========================

my $hash_param ; # individual hash rows.
my $key ; # key for hash_param row.
my $value ; # value for hash_param row.
my $code_module ; # holds name of each code module.

#-------------------------------------------------------------------------------------
# Open parameter file and hash old/new database names, and path to appropriate logon file.
# ========================================================================================

my $success = open FILE_PATH, "<$location" ;
unless ($success) {
&err_open ( $location )
}

while (<FILE_PATH>) {
($key, $value) = split(/:\s*/, $_) ;
chomp ( $key ) ; chomp ( $value ) ;
$hash_param { lc ( $key ) } = $value ;
}

close FILE_PATH ;

#-------------------------------------------------------------------------------------
# Read code module name and call chg_schema subroutine.
# =====================================================

$success = open CODE_MODULE, "<$file_lst" ;
unless ($success) {
&err_open ( $file_lst )
}

while ($code_module = readline CODE_MODULE) {
&chg_schema ( $code_module ) ;
}

close CODE_MODULE ;

exit 0 ;

#-------------------------------------------------------------------------------------
# Subroutine to change code schema.
# =================================

sub chg_schema {

my $file = <$_[0]> ;
print "file: $file\n:" ;
my $success = open FILE_IN, "<$file" ;
unless ($success) {
&err_open ( $file )
}

local $/ ; # enable slurp mode so that entire file is stored in a single variable.

my $lines = lc(<FILE_IN>) ;

print "lines: $lines" ;
close FILE_IN ;

print "old_db: " ; print $hash_param {"old_db"} ; print "\n" ;
print "new_db: " ; print $hash_param {"new_db"} ; print "\n" ;

if (exists $hash_param{"sandbox"}) {
print "old_db value exists\n" ;
} else {
print "no match for old_db\n" ;
}

$success = open ( FILE_OUT , ">$file" ) ;
unless ($success) {
&err_open ( $file )
}

for ( $lines ) {
#$# s/sandbox/production/g ;
s/$hash_param {"old_db"}/$hash_param {"new_db"}/g ; #%#
print FILE_OUT ;
}

close FILE_OUT;
}

#-------------------------------------------------------------------------------------
# Subroutine to process file-open errors.
# =======================================

sub err_open {
system "touch tiv_inst.err" ;
system "date +%Y%m%d-%T" ;
die "File open failure: $_[0]\n$!" ;
}

### File contents listed below; actual files do not include '#' symbol. ###
#-------------------------------------------------------------------------------------
# Contents of path.logon.
# =======================
#old_db: sandbox
#new_db: production
#path: /home/ken/chek

#-------------------------------------------------------------------------------------
# Contents of objects.lst.
# ========================
#test1.vew

#-------------------------------------------------------------------------------------
# Contents of test1.vew.
# ======================
#replace view sandboxv.test1 as
#select * from sandboxt.event;
 
Old 12-08-2006, 06:51 AM   #2
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: NetBSD, Void, Debian, Mint, Ubuntu, Puppy, Raspbian
Posts: 3,487

Rep: Reputation: 233Reputation: 233Reputation: 233
substitute in place this for that

Code:
perl -pi.bak -e 's/this/that/g' file1 file2 ...
 
Old 12-08-2006, 08:54 AM   #3
WindozBytes
Member
 
Registered: Aug 2001
Location: CT, USA
Distribution: Mandriva 2008
Posts: 105

Original Poster
Rep: Reputation: 15
Thanks for the tip on editing in-place; now I won't need that ugly subroutine. However, I am still left with the original problem that the hash keys do not match a string from the source files. I can get it to work if I read the keys/values into an array, then hash the array, but that seems like such a kluge.
 
Old 12-08-2006, 09:16 AM   #4
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: NetBSD, Void, Debian, Mint, Ubuntu, Puppy, Raspbian
Posts: 3,487

Rep: Reputation: 233Reputation: 233Reputation: 233
how is your file organised? key value pairs?
if so slurp into an array and convert to a hash,
easy...

Code:
open IN "< your file";
@array = <IN>;
chomp @array;
%hash = @array;
 
Old 12-08-2006, 09:57 AM   #5
WindozBytes
Member
 
Registered: Aug 2001
Location: CT, USA
Distribution: Mandriva 2008
Posts: 105

Original Poster
Rep: Reputation: 15
Still not finding a match; the line for invoking the substitution now looks like this:

`/usr/bin/perl -pi -e "s/$hash_param{old_name}/$hash_param{new_name}/gi" $code_module` ;

Is there something obvious about how I'm invoking the substitution that's precluding a match?
 
Old 12-08-2006, 10:35 AM   #6
WindozBytes
Member
 
Registered: Aug 2001
Location: CT, USA
Distribution: Mandriva 2008
Posts: 105

Original Poster
Rep: Reputation: 15
I finally got it to work by using the following:
my $old_name = $hash_param {"old_name"} ; chomp $old_name ;
my $new_name = $hash_param {"new_name"} ; chomp $new_name ;
`/usr/bin/perl -pi -e "s/$old_name/$new_name/gi" $code_module` ;
I may be able to tinker with it and get rid of the extraneous newline character in the hash that was preventing the match without resorting to the temporary names, but I've already spent far too much time with this....

Thanks again for the assist.
Regards,
Ken~
 
Old 12-10-2006, 05:20 PM   #7
chrism01
LQ Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 7.7 (?), Centos 8.1
Posts: 17,843

Rep: Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572Reputation: 2572
In the OP, conventionally you'd reverse the order of:

($key, $value) = split(/:\s*/, $_) ;
chomp ( $key ) ; chomp ( $value ) ;

assuming each key-val pair is basically

key : val \n

ie chomp the rec once, then split key/val into vars.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
command line edit -- global find/replace on text file w/o going into vi car182 Linux - Newbie 4 05-25-2006 05:42 PM
global search and replace? jkcunningham Linux - General 5 03-15-2006 02:43 PM
Using hash value as key for other hash in Perl scuzzman Programming 6 02-14-2006 05:08 PM
Hash-sort like in PERL in C++ nyk Programming 4 06-11-2004 08:40 AM
problem in perl replace command with slash (/) in search/replace string ramesh_ps1 Red Hat 4 09-10-2003 01:04 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:09 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration