madmonster99 has asked for the wisdom of the Perl Monks concerning the following question:

I have access to the /etc/passwd file. I'm trying to write a program that reads the file /etc/passwd and prints the list of usernames and names of the users contained in the file. The output needs to be in the format: username_1 name_1 username_2 name_2 The code for this problem that I am using is this: - UW PICO(tm) 4.5 File: password5.pl-----------------------------
#!/usr/bin/perl -lne 'print (split(/:/))[0]' /etc/passwd
and the error i get is this: et791:~$ ./password5.pl String found where operator expected at ./password5.pl line 3, near "lne 'print (split(/:/))0'" (Do you need to predeclare lne?) syntax error at ./password5.pl line 3, near "lne 'print (split(/:/))0'" Execution of ./password5.pl aborted due to compilation errors. Can someone please help me???

Replies are listed 'Best First'.
Re: printing passwd file
by ikegami (Patriarch) on Mar 14, 2005 at 17:10 UTC

    perl -lne 'print (split(/:/))[0]' /etc/passwd should be typed as-is on the shell command line. The script version of it would be:

    open(PASSWD, '/etc/passwd/') or die("Can't open the system password file: $!\n"); print((split(/:/))[0], "\n") while (<PASSWD>); close(PASSWD);
Re: printing passwd file
by eieio (Pilgrim) on Mar 14, 2005 at 17:12 UTC
    If you want a one-liner:
    perl -lne 'print ((split /:/)[0])' /etc/passwd

    I noticed that you specified that the output should contain the user name as well as the name, but your code only displayed the user name. If you need both:

    perl -lne 'print ((split /:/)[0] . " " . (split /:/)[4])' /etc/passwd

      You can also use this:

      perl -wlne 'print join " ", (split /:/)[0, 4]' /etc/passwd
        And arbitrarily playing golf:
        perl -lne 'print "@{[(split /:/)[0, 4]]}"' /etc/passwd
        Or particularly well suited to -a and -F:
        perl -F: -lane 'print "@F[0, 4]"' /etc/passwd

        --
        [ e d @ h a l l e y . c c ]

Re: printing passwd file
by gellyfish (Monsignor) on Mar 14, 2005 at 17:24 UTC

    I think you mean:

    #!/usr/bin/perl # + + while ( my $user = (getpwent())[0]) { print $user,"\n"; }

    /J\

Re: printing passwd file
by sh1tn (Priest) on Mar 14, 2005 at 17:11 UTC
    # cli: perl -pne 's/(.+?):.+/user_$. $1_$./' /etc/passwd # or from file: #!/usr/bin/perl -np s/(.+?):.+/user_$. $1_$./
    Update: instead of "username_1 name_1" format you may want "username_1 name"
    in which case substitute $1 for $1_$..


Re: printing passwd file
by ambrus (Abbot) on Mar 14, 2005 at 17:16 UTC

    You'll need a plus after print, like this: print+(split(/:/))[0]

    (Update: see the beginning of perldoc perlfunc if you don't know why.)

    You'll need the perl options and arguments in the shebang line, or make a shell script of this, like

    #!/bin/sh perl -lne 'print+(split(/:/))[0]' /etc/passwd
    or else
    #!/usr/bin/perl -ln BEGIN{ @ARGV = "/etc/passwd"; } print+(split(/:/))[0]
    or even
    #!/usr/bin/perl -w @ARGV = "/etc/passwd"; $\ = $/; while(<>) { print+(split(/:/))[0]; }
Re: printing passwd file
by ww (Archbishop) on Mar 14, 2005 at 17:31 UTC

    updateAmbrus read more carefully than I. new text and strikes are updates

    Madmonster:

    Please keep followups (such as this is, mimimally) in the original thread rather than starting a new one, Reposting an essentially verbatim question to a new node is NOTNOT regarded as honorable conduct in the monastery, particularly when the monks have already replied to your original ( password file problem, posted 3 days earlier than this one); offering answers most of which you do NOT appear to have studied and explaining WHY some of what you've posted WON'T WORK.

    Failing to use <code> tags around your sample of what "output needs to be..." and your error messages is conterproductive, as omitting them lessens the readability of your post.

    Please consult: How do I post a question effectively? AND (if you need more on formatting) Writeup Formatting Tips. Note that <code> tags are allowed around content that is NOT code, when their use makes your post more legible.

    ... and you may want to review the use of "-lne" (ps: that's one that's already been answered in a reply to your original post), and start using warnings and strict, qv.

Re: printing passwd file
by Anonymous Monk on Mar 14, 2005 at 17:25 UTC
    perl -aF: -lpe'$_=$F[0]' /etc/passwd perl -le'print while $_=getpwent'
    HTH. HAND.
Re: printing passwd file
by holli (Abbot) on Mar 14, 2005 at 18:47 UTC
    Mmh, nothing on CPAN for this? I expected to find something like Passwd::Parse but for no avail.

    Update: *Ouch.*


    holli, /regexed monk/

      You mean aside from Unix::PasswdFile, Passwd::Solaris and Passwd::Linux, or AnyData::Format::Passwd?

      Or the built-in getpwent and friends? (Which has the benefit of probably honoring the local system's NIS or other remote password source)

      Nope. nothing.

      Update: OK, those middle two are for adding and removing new entries from the corresponding OS' passwd files rather than parsing out contents so they probably don't count as "parsing passwd" modules.

      There's a function -- getpwent, so I guess there hasn't been as much need for it. (besides, it's just a colon delim file, so most other parsing programs could do it).

      I'd also like to point out that there is no 'name' field in a passwd file -- it's the gecos field, which contains a comma seperated list of optional comments, the first of which is typically the name. (which is why you get odd behavior when someone tries entering a name in 'last, first' format.) From perldoc -f getpwent :

      The exact meaning of the $gcos field varies but it usually contains the real name of the user (as opposed to the login name) and other information pertaining to the user. Beware, however, that in many system users are able to change this information and therefore it cannot be trusted and therefore the $gcos is tainted (see perlsec). The $passwd and $shell, user's encrypted password and login shell, are also tainted, because of the same reason.
      Maybe I have put the wrong name - it is quite "silent",
      but what can be more expressive than usermod?
      #!/usr/bin/perl use strict; use Linux::usermod; my %users = Linux::usermod::users(); print join "\n", keys %users __END__ # STDOUT: backup bin cv daemon games gnats helpdesk identd irc list lp mail man mysql netsaint news nobody operator popa3d postfix postgres proxy reni root snort spong sshd su sync sys uucp vidul vis www-data # all those looks like system user accounts to me :)