Reputation: 17
I am working on a perl script that finds will take customer service information and change the service ids. The code i have now can take a 2 column csv file for reference, and swap the numbers, but when i try to use "\n" or "\|" like i need to, it will give me the `ol:
"sed: -e expression #1, char 29: unterminated `s' command"
Here's my original code that works for changing JUST the number within the quotes:
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV; #load Text::CSV module for parsing CSV
use LWP::Simple; #load LWP module for doing HTTP get
my $file = 'sid_swap.csv'; #CSV file to parse and load
my $csv = Text::CSV->new(); #create a new Text::CSV object
open (CSV, "<", $file) or die $!; #open CSV file for parsing
while (<CSV>) {
if ($csv->parse($_)) {
my @columns = $csv->fields(); #parse csv files and load into an array for each row
my $newSID = $columns[0];
my $oldSID = $columns[1];
system("sed -i 's/\<row SERVICE_MENU_ID=\"$oldSID\"/\<row SERVICE_MENU_ID=\"$newSID\"/g' customer_data.txt");
} else {
my $err = $csv->error_input;
print "Failed to parse line: $err";
}
}
close CSV;
And here is the new code that throws the error:
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV; #load Text::CSV module for parsing CSV
use LWP::Simple; #load LWP module for doing HTTP get
my $file = 'sid_swap.csv'; #CSV file to parse and load
my $csv = Text::CSV->new(); #create a new Text::CSV object
open (CSV, "<", $file) or die $!; #open CSV file for parsing
while (<CSV>) {
if ($csv->parse($_)) {
my @columns = $csv->fields(); #parse csv files and load into an array for each row
my $newSID = $columns[0];
my $oldSID = $columns[1];
system("sed -i 's/\<row SERVICE_MENU_ID=\"$oldSID\"/\n$newSID\|/g' customer_data.txt");
} else {
my $err = $csv->error_input;
print "Failed to parse line: $err";
}
}
close CSV;
Thanks for any help you can provide!
Upvotes: 0
Views: 971
Reputation: 386676
To debug, change system("sed ...")
to die("sed ...");
. You'll see you're what trying to execute
sed -i 's/<row SERVICE_MENU_ID="OLDSID"/
NEWSID|/g' customer_data.t
I guess sed
doesn't like actual newlines in the middle of its arguments? That can be fixed using proper escaping, but your approach is... insane. You're processing the entire file for each row of the CSV!
open(my $CSV, "<", $file) or die $!; # Let's not use global vars!
my %fixes;
while (<$CSV>) {
$csv->parse($_)
or die "Failed to parse line: ".$csv->error_input."\n";
my ($newSID, $oldSID) = $csv->fields();
$fixes{$oldSID} = $newSID;
}
my $pat = join "|", map quotemeta, keys(%fixes);
my $re = qr/$pat/;
{
local @ARGV = 'customer_data.txt';
local $^I = ''; # "perl -i" mode
while (<>) {
s/<row SERVICE_MENU_ID="($re)"/\n$fixes{$1}|/g;
print;
}
}
Doing it in one pass also solve the problem of
1111,2222
2222,3333
being the same as
1111,3333
2222,3333
Upvotes: 4