can substitute and end of string

Discussion in 'Perl Misc' started by marcorice@gmail.com, Aug 3, 2005.

  1. Guest

    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;
    , Aug 3, 2005
    #1
    1. Advertising

  2. Paul Lalli Guest

    wrote:
    > 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
    Paul Lalli, Aug 3, 2005
    #2
    1. Advertising

  3. Guest

    >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
    , Aug 3, 2005
    #3
  4. Guest

    wrote:
    > >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,


    OK, what about non-printing characters? Got any of those?
    , Aug 3, 2005
    #4
  5. Paul Lalli Guest

    wrote:
    > Paul Lalli wrote:
    > >
    > >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*/;


    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
    Paul Lalli, Aug 3, 2005
    #5
  6. At 2005-08-03 11:53AM, <> wrote:
    > >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



    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?


    --
    Glenn Jackman
    NCF Sysadmin
    Glenn Jackman, Aug 3, 2005
    #6
  7. Guest

    >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.
    , Aug 3, 2005
    #7
  8. Paul Lalli Guest

    wrote:
    > 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
    Paul Lalli, Aug 3, 2005
    #8
  9. wrote:
    > 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

    --
    Josef Möllers (Pinguinpfleger bei FSC)
    If failure had no penalty success would not be a prize
    -- T. Pratchett
    Josef Moellers, Aug 4, 2005
    #9
  10. Guest

    >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 |
    , Aug 4, 2005
    #10
  11. Paul Lalli Guest

    wrote:
    > >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.


    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'

    <snip a bunch of irrelevant code>

    > #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.
    Paul Lalli, Aug 4, 2005
    #11
  12. Guest

    >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!
    , Aug 4, 2005
    #12
  13. Paul Lalli Guest

    wrote:
    > >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 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
    Paul Lalli, Aug 4, 2005
    #13
  14. Guest

    >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.
    , Aug 4, 2005
    #14
  15. Paul Lalli Guest

    wrote:
    > >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.


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

    Paul Lalli
    Paul Lalli, Aug 4, 2005
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jeff Kish
    Replies:
    2
    Views:
    906
    Jeff Kish
    Nov 15, 2004
  2. Lingyun Yang
    Replies:
    2
    Views:
    489
    Daniel T.
    Apr 10, 2004
  3. Replies:
    7
    Views:
    765
    Pasi Savolainen
    Feb 26, 2006
  4. Casanova

    Macro without string to substitute

    Casanova, Nov 21, 2004, in forum: C Programming
    Replies:
    6
    Views:
    390
    Richard Bos
    Nov 24, 2004
  5. Replies:
    4
    Views:
    475
    Stan Milam
    Apr 30, 2005
Loading...

Share This Page