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

hi,

i have a question i was wondering if someone can help me with i had written a bash script that count how many people are using each shell. i have done my best to convert it into perl but still getting errors. when run it tells me there are errors but i can not seem to find them. any help would be much appreciated. here is my code

#!/usr/bin/perl #===================================================================== +======= # Scipt Name : usage_menu # By: Joshua Spradling # Purpose: Give user the choice of getting shell information from s +ystem # and printing usage message and quitting # command line: usage_menu #===================================================================== +======= $usagefile = '/etc/passwd'; sub list_users { print "in list users "; $ct= awk -F: { print "$7" } $usagefile ; print $ct; # more /etc/passwd exit 1; } sub count_usage { print "users usage\n "; print "============\n"; print "The number of bash users\n"; open $usagefile | grep "bash" | ++$bashCounter | print("$bashCounte +r"); print "The number of no login\n"; open $usagefile | grep "nologin" | ++$noLoginCounter | print("$noLo +ginCounter"); print "The number of csh users\n"; open $usagefile | grep "csh" | ++$cshCounter | print("$cshCounter") +; print "The number of ksh user\n "; open $usagefile | grep "ksh" | ++$kshCounter | print("$kshCounter") +; } $loop=y; while (<"$loop" = "y">) { print " Usage Menu \n"; print "==============\n"; print "[1] - Get shell information from system \n"; print "[2] - Print a usage message \n"; print "[Q] - Quit \n"; print "\n"; read $choice || continue; for($choice){ if (/1/) {list_users}; elsif (/2/) {count_usage}; elsif (/Q/) {exit}; else {print "error" }; } }

thank you
very respectfully josh

Replies are listed 'Best First'.
Re: BASH SCRIPT s TO PERL
by davido (Cardinal) on Apr 25, 2014 at 01:50 UTC

    When you got a bunch of error messages, did you look at them and try to figure out what they were telling you? Typically the best place to start is with the first message. Resolve it, then move on by re-testing. It's usually not as productive to look at the second, third, and so on, as they may be artifacts of the problem that triggered the first message. So solve the first, re-test, solve the new first message, and so on.

    In this case, the first message is, "Unquoted string "awk" may clash with future reserved word at mytest.pl line 14.". At this point someone wanting to solve a problem himself would think, "Hmm. I wonder what that means?" Possibly that this line:

    $ct= awk -F: { print "$7" } $usagefile ;

    ...is malformed in some way, and probably in some way that has to do with quoting. How should we quote something that we intend to pass to the shell? perlop discusses the backtick quotes: ``. Let's wrap the appropriate part of that line in backticks and see what error we come up with next.

    $ct= `awk -F: { print "$7" } $usagefile`;

    And now perl -c mytest.pl: "syntax error at mytest.pl line 38, near "print"". Let's investigate that. The way I have your script loaded in my editor line 38 is this:

    print "[1] - Get shell information from system \n";

    Since there's nothing wrong there that I can see we need to look at the line before (Perl hasn't gotten to the line after yet, so the place to look if this line isn't the problem is the line(s) preceding.) It turns out I have to walk backward five lines to figure out where it is that Perl is getting confused. It's this line:

    $loop=y;

    y isn't wrapped in quotes, so Perl thinks it's the start of the tr/// (or in other words y///) operator (see perlop again). That needs to be quoted. Let's fix it: $loop="y";

    Now we'll test again: perl -c ./mytest.pl spits out several errors, but the first (because we always look at the first one first) is this: Not enough arguments for read at mytest.pl line 42, near "continue;". The line in question is:   read $choice || continue;. So let's look up read in Perl's documentation and see what the problem is. Read takes a filehandle first, then a scalar where the data being read should be read into. It also needs a length and an offset. Hmm... we didn't give it a filehandle. Where should we get one of those? Maybe we should back up a little and read perlintro before we go any further. That document has a section on file IO, and more importantly, demonstrates the while(<$fh>) idiom, which in your case (since I think you intend to be taking user input from the keyboard) should probably be the while(<STDIN>){... idiom instead.

    I'm going to stop there; you should read perlintro. I could write it for you, but then you would have a working script (the easy part), but not the knowledge to handle the next problem that comes up in the future (learning is the harder part, right?). Read perlintro, then take a stab at figuring out the user input stuff. Post here when/if you have additional problems.

    Finally, I do want to mention the last syntax error that will turn up later on: In Perl, you shouldn't put a semicolon between if(...){....} and the elsif(...) constructs. Doing so is a syntax error.


    Dave

Re: BASH SCRIPT s TO PERL
by 2teez (Vicar) on Apr 25, 2014 at 01:53 UTC

    hi Jspradling84,

    ..i have a question i was wondering if someone can help me with i had written a bash script that count how many people are using each shell..

    May be you want to look at getpwent in perl.

    Something like this should do:

    use warnings; use strict; my %shell; while ( my ($ui) = ( getpwent() )[8] ) { $shell{$ui}++; } print $shell{$_}, ' person(s) uses ', $_, $/ for keys %shell;

    If you tell me, I'll forget.
    If you show me, I'll remember.
    if you involve me, I'll understand.
    --- Author unknown to me