can substitute and end of string

M

marcorice

I'm trying to a substitute in a password and shadow file and perl will
not let me do it for the end of string, can anyone help.

#this works for begin of string.
$line =~ s/^$unixid/$nitd/g;
$line =~ s/\A$unixid/$nitd/g;

#this does not for end of string.
$line =~ s/$unixid$/$ntid/g;
$line =~ s/$unixid\z/$ntid/g;
$line =~ s/$unixid\Z/$ntid/g;

#so therefore this does not for begin and end.
$line =~ s/^$unixid$/$ntid/g;
 
P

Paul Lalli

I'm trying to a substitute in a password and shadow file and perl will
not let me do it for the end of string, can anyone help.

#this works for begin of string.
$line =~ s/^$unixid/$nitd/g;
$line =~ s/\A$unixid/$nitd/g;

#this does not for end of string.
$line =~ s/$unixid$/$ntid/g;
$line =~ s/$unixid\z/$ntid/g;
$line =~ s/$unixid\Z/$ntid/g;

All of those match the "end" (for various definitions of end).
Therefore, I predict that either $line does not contain what you think
it contains, or that $unixid does not contain what you think it
contains.

Please print out both values, demarking the beginning and end:
print "Line: |$line|\n";
print "UnixId: |$unixid|\n";

And see if there is any unexpected whitespace before the terminating |
character.

Paul Lalli
 
M

marcorice

Please print out both values, demarking the beginning and end:
print "Line: |$line|\n";
print "UnixId: |$unixid|\n";
I checked and there are no terminating nor begining whitespace, here's
a little more the code.
# Traverse the UIDs_n_IDs_Not_Match file and Read & Substitute unix ids
w/ NT ids.
foreach (@name_change2) {
my
($NULL1,$unixid,$NULL2,$unixuid,$NULL3,$NULL4,$ntid,$NULL5,$ntuid) =
split /\s*\|\s*/;
$line =~ s/$unixid/$ntid/g;

} #end of foreach
 
P

Paul Lalli

I checked and there are no terminating nor begining whitespace, here's
a little more the code.
# Traverse the UIDs_n_IDs_Not_Match file and Read & Substitute unix ids
w/ NT ids.
foreach (@name_change2) {
my
($NULL1,$unixid,$NULL2,$unixuid,$NULL3,$NULL4,$ntid,$NULL5,$ntuid) =
split /\s*\|\s*/;

You seem to have ignored the advice I gave yesterday about how to clean
this up.
$line =~ s/$unixid/$ntid/g;

} #end of foreach

There is no attempt to match the end of the string in this code.

Please post a SHORT BUT COMPLETE script that SHOWS THE PROBLEM you are
encountering. Make sure you include statements that will cause the
relevant data to be identified (ie, the aforementioned print
statements). Also include the erroneous output that this short but
complete script generates.

Paul Lalli
 
G

Glenn Jackman

At 2005-08-03 11:53AM said:
I checked and there are no terminating nor begining whitespace, here's
a little more the code.
# Traverse the UIDs_n_IDs_Not_Match file and Read & Substitute unix ids
w/ NT ids.
foreach (@name_change2) {
my
($NULL1,$unixid,$NULL2,$unixuid,$NULL3,$NULL4,$ntid,$NULL5,$ntuid) =
split /\s*\|\s*/;
$line =~ s/$unixid/$ntid/g;

} #end of foreach


Are you trying to match the string contained in $line (where is it
defined?) or $_ ? Do you have:
use strict;
use warnings;
in your code?
 
M

marcorice

You seem to have ignored the advice I gave yesterday about how to clean
this up.
$line =~ s/$unixid/$ntid/g;
} #end of foreach
I tried your suggestion from yesterday.
my ($unix_id2, $unixuid2, $ntid, $ntuid) = (split /\s*\|\*s/)[1,3,6,8];

it returns BLANK,and
$line =~ s/\Q^$unixid$\E/$ntid/g;
has the same affect as before and yes i'm using strict but not
warnings, it's not on my system.
 
P

Paul Lalli

Paul Lalli wrote

(attribution added back in - please stop snipping that)
You seem to have ignored the advice I gave yesterday about how to clean
this up.
$line =~ s/$unixid/$ntid/g;
} #end of foreach
I tried your suggestion from yesterday.
my ($unix_id2, $unixuid2, $ntid, $ntuid) = (split /\s*\|\*s/)[1,3,6,8];

it returns BLANK,and

I fail to believe you. Please post a short but complete script that
shows your version of that line succeeding, but mine failing.
$line =~ s/\Q^$unixid$\E/$ntid/g;
has the same affect as before and yes i'm using strict but not
warnings, it's not on my system.

If your version of perl is old enough to not have warnings.pm, then are
you at least using
-w
on the shebang line?

One more time, I am asking you to post a short but COMPLETE program.
Until that happens, I'm done with this thread, and wish you well.

Paul Lalli
 
J

Josef Moellers

I'm trying to a substitute in a password and shadow file and perl will
not let me do it for the end of string, can anyone help.

#this works for begin of string.
$line =~ s/^$unixid/$nitd/g;
$line =~ s/\A$unixid/$nitd/g;

#this does not for end of string.
$line =~ s/$unixid$/$ntid/g;
$line =~ s/$unixid\z/$ntid/g;
$line =~ s/$unixid\Z/$ntid/g;

#so therefore this does not for begin and end.
$line =~ s/^$unixid$/$ntid/g;

Could it be that wour $line (still) contains a newline character at the
end, therefore having $unixid _not_ at the end?

perldoc -f chomp
 
M

marcorice

One more time, I am asking you to post a short but COMPLETE program.
Until that happens, I'm done with this thread, and wish you well.
Paul Lalli
OKAY, here's the code, everthing works except when i want to do begin
and end substitution. I've only coding perl for a MONTH.
#!/bin/perl

use strict;
use Sys::Hostname;
use File::Copy;
chomp(my $date = `date '+%m%d%y'`);
#I know this looks a little messed up but works.
my $name_change = "./UIDs_n_IDs_Not_Match";
open(name_change,"$name_change") or die ("Can't open
$name_change:$!\n");
my @name_change2 = <name_change>;
# Checking Host
if ($host eq "powerhouse"){
# Setup output files
my $passwd_out = "passwd.out";
open (passwdout,">$passwd_out") or die ("Can't create $passwd_out
file: $!\n");
my $shadow_out = "shadow.out";
open (shadowout,">$shadow_out") or die ("Can't create $shadow_out
file: $!\n");
my $group_out = "group.out";
open (groupout,">$group_out") or die ("Can't create $group_out file:
$!\n");
my $passwd_file = "/etc/passwd";
my $shadow_file = "/etc/shadow";
my $group_file = "/etc/group";
copy("$passwd_file","$passwd_file.$date");
copy("$shadow_file","$shadow_file.$date");
copy("$group_file","$group_file.$date");
@ARGV=("$passwd_file","$shadow_file","$group_file");
while (my $line=<>) {
#@pass_info = getpwnam((split(/:/,$_))[0]);

# Traverse the UIDs_n_IDs_Not_Match file and R&R unix ids w/ NT
ids.
foreach (@name_change2) {
my
($NULL1,$unixid,$NULL2,$unixuid,$NULL3,$NULL4,$ntid,$NULL5,$ntuid) =
split /\s*\|\s*/;
#THIS WORKS BUT I DON'T WANT TO USE "^$unixid:" I WANT TO USE
"^$unixid$"
$line =~ s/^$unixid:/$ntid:/g;

} #end of foreach

if ($ARGV eq "$passwd_file") { print passwdout $line; }
elsif ($ARGV eq "$shadow_file") { print shadowout $line; }
elsif ($ARGV eq "$group_file") { print groupout $line; }
}

# Close input files
close (name_change);
# Close output files
close (passwdout) or die ("Can't close passwd.out file; $!\n");
close (shadowout) or die ("Can't close shadow.out file; $!\n");
close (groupout) or die ("Can't close group.out file; $!\n");
move("$passwd_out","/tmp/passwd.mv") or warn "Move Failed: $!";
chmod(0444, "/tmp/passwd.mv") or warn "chmod Failed: $!";
} #end if

Here's an example of the UIDs_n_IDs_Not_Match file

UnixUserID | dopey | UID | 10 | does not match LOGIN and UID found in
LDAP | ldapusername | jdoe | LDAPUID | 106520 | UNIXNAME | John Doe |
LDAPname | John Doe | UnixEmployid | 00000 | LDAPemployid | 00000 |
email | (e-mail address removed)
 
P

Paul Lalli

OKAY, here's the code, everthing works except when i want to do begin
and end substitution. I've only coding perl for a MONTH.

The length of time you've been coding in Perl is irrelevant.

What is relevant is that you continue to ignore my requests - although
I admit you did better this time.
* You still have not reduced your problem to the *shortest* script
that demonstrates the issue you're having. (Why would you bother
showing us a bunch of code that does work?)
* You still have not included lines that print the values of $line,
$unixid, and any other relevant variables.
* You still do not have warnings enabled, either through 'use
warnings;' or '-w'

#THIS WORKS BUT I DON'T WANT TO USE "^$unixid:" I WANT TO USE
"^$unixid$"

What on earth makes you believe that /^$unixid:/ working would imply
that /^$unixid$/ should also work? In fact, I'd say it's a fact that
that would NEVER be true. If the string matches $unixid, followed by a
colon, it cannot possibly match $unixid followed by the end of string.
Here's an example of the UIDs_n_IDs_Not_Match file

Which is wholly unnecessary. The only relevant values are the current
contents of $line and $unixid, and any error messages you receive.

The following is a short-but-complete program in the style you should
be showing us:

#!/usr/bin/perl -w
use strict;

chomp(my $line = <DATA>);
my $unixid = 'dopey';
my $replace = 'foobar';

print "Line: !$line!\n";
print "Unixid: !$unixid!\n";

$line =~ s/^\Q$unixid\E:$/$replace:/;

print "Line now: !$line!\n";

__DATA__
dopey:

Output:
Line: !dopey:!
Unixid: !dopey!
Line now: !foobar:!


Modify this code to show us the exact issue you're seeing. Keep the
debugging outputs.
 
M

marcorice

What on earth makes you believe that /^$unixid:/ working would imply
that /^$unixid$/ should also work? In fact, I'd say it's a fact that
that would NEVER be true. If the string matches $unixid, followed by a
colon, it cannot possibly match $unixid followed by the end of string.
Now i understand how to properly post now.
/^$unixid:/ works because the variable is followed by a : it's the only
end placeholder that i have, later on i will be substituting where
there won't be a :.
I tried your code with only the exception of $unixid = 'root'; because
dopey is not really in the /etc/password file, and the end $ cause it
not to work.


_DATA_
root:
Output:
Line: !root:x:0:1:Super-User - SHARED ACCOUNT:/:/bin/ksh!
Unixid: !root!
Line now: !root:x:0:1:Super-User - SHARED ACCOUNT:/:/bin/ksh!
 
P

Paul Lalli

Now i understand how to properly post now.
/^$unixid:/ works because the variable is followed by a : it's the only
end placeholder that i have, later on i will be substituting where
there won't be a :.

I think you're very confused about what $ does in a pattern match.

This code:
$line =~ /^$unixid:/
Says to search $line for: The beginning of the string, followed by
what's in $unixid, followed by a semicolon.

This code:
$line =~ /^$unixid$/
Says to search $line for: The beginning of the string, followed by
what's in $unixid, followed by the end of the string. It is (almost)
exactly equivalent to:

$line eq $unixid

If $line contains $unixid, followed by *anything* (other than a
newline), that pattern match will fail. That's what it's supposed to
do.
I tried your code with only the exception of $unixid = 'root'; because
dopey is not really in the /etc/password file, and the end $ cause it
not to work.


_DATA_
root:
Output:
Line: !root:x:0:1:Super-User - SHARED ACCOUNT:/:/bin/ksh!
Unixid: !root!
Line now: !root:x:0:1:Super-User - SHARED ACCOUNT:/:/bin/ksh!

That is exactly what is supposed to happen. $line DOES NOT CONTAIN the
pattern you are trying to replace.

This all started when you posted "I want to match the beginning and end
of the string". I see now that I should have asked what you mean by
that. What is your reason for wanting to use the $ in the pattern
match to begin with?

I have a distinct feeling what you really wanted to do was match
"beginning of a word, followed by $unixid, followed by the end of the
word". In other words, to match
root
but not
rooty

In that case, $ is NOT the token you want to use. Instead, you can use
\b to match word boundaries, like so:

$line =~ /\b$unixid\b/

Read more about these "zero-width assertions" in:
perldoc perlretut
perldoc perlre
perldoc perlreref

Paul Lalli
 
M

marcorice

In that case, $ is NOT the token you want to use. Instead, you can use
\b to match word boundaries, like so:
$line =~ /\b$unixid\b/

You're a GENIOUS, that works, I AM SO SORRY for occupying your time
like this and you have been very patient and understanding. I was
begining to think that i had made a big mistake trying to code in perl.
Thanks again.
 
P

Paul Lalli

You're a GENIOUS, that works, I AM SO SORRY for occupying your time
like this and you have been very patient and understanding. I was
begining to think that i had made a big mistake trying to code in perl.
Thanks again.

You're very welcome. Glad it all worked out for you. Sorry for the
communications difficulties.

Paul Lalli
 

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

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top