• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 183
  • Last Modified:

Need help with grep or matching user input

Hello, I have now received another requirement for the script that I've modified.  I've attached the script, it's working, and now my issue is that when I issue a ./fc.pl %eli31*, they want anything with eli31 to be displayed, and nothing else.  Please help, thanks.
i.e.
./fc.pl %eli31*
Command: fc.pl -s test310:19018 '@fc '

        Client: /ELF310      Node: test310
        ProcName: Eli31Fix0    

         CONNECTIONS
+----------------------+--------------+--------------+-----------+-----------+-+
|   Connection Name    |  API State   |  Fix State   |  Rx Msgs  |  Tx Msgs  | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31PRIMARY           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP          | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP2           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI23PRIMARY    | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| TEST_PRIMARY     | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| TEST_PRIMARY_2     | DisConnected | DisConnected | 000000000 | 000000000 | |

======================================================================
The new way the output should look like:
./fc.pl %eli31*
Command: fc.pl -s test310:19018 '@fc '

        Client: /ELF310      Node: test310
        ProcName: Eli31Fix0    

         CONNECTIONS
+----------------------+--------------+--------------+-----------+-----------+-+
|   Connection Name    |  API State   |  Fix State   |  Rx Msgs  |  Tx Msgs  | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31PRIMARY           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP          | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP2           | DisConnected | DisConnected | 000000000 | 000000000 | |
I've written the following code towards the end of the script but it's not working plus it's giving me some errors that I don't understand.  Here's my error:  
Scalar value @ARGV[1] better written as $ARGV[1] at ./cbscmd4fc line 300.
Scalar value @ARGV[1] better written as $ARGV[1] at ./cbscmd4fc line 302.
 
New code was inserted at line 298.
 my $process = "";
 
 for(my $i = 0; $i <= length(@ARGV[1]); $i++) {
       my $char;
       $char = substr(@ARGV[1], $i, 1);
       if($char =~ /\% [A-Za-z] /) {
               $process = $process.$char;
#print "test $process.$char";
       }
}
 
## if($_ =~ /@ARGV[0]/
                       print "$_";
                  ....

Open in new window

0
bb0812
Asked:
bb0812
  • 13
  • 8
  • 7
2 Solutions
 
Adam314Commented:
@ARGV is an array.  $ARGV[1] is the second (first is index 0) element of that array.  @ARGV[1] is an array slice - a part of the array - in this case, an array containing the second element of @ARGV. The warnings are telling you that instead of @ARGV[1], you should be using $ARGV[1].

And since it looks like you want the first argument, not the second, you probably want the 0'th index: $ARGV[0].
0
 
bb0812Author Commented:
I changed the code but I still don't get the output I want.  I do not get the errors anymore, and I changed the value from 1 to 0 to no avail.

my $process = "";
print "@resp";
  for(my $i = 0; $i <= length($ARGV[0]); $i++) {
        my $char;
        $char = substr($ARGV[0], $i, 1);
        if($char =~ /\% [A-Za-z] /) {
                $process = $process.$char;
print "test $process.$char";
 
        }
 }

Open in new window

0
 
Adam314Commented:
I'm not sure what you are trying to do with your code, but if the goal is to remove anything that isn't a percent or a letter, you can use this:
$ARGV[0] =~ s/[^%A-Za-z]//g;

Open in new window

0
The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

 
bb0812Author Commented:
The $ARGV variable contains the command @fc %eli23*, I'm trying to get any instance of eli23 and just output that.
Can I use grep instead, if so how.
All I want is to get the output of whatever I type.  For instance, if I have typed, ./fc.pl %test*, I should get test_primary, and test_primary_1.  
0
 
ozoCommented:
all unix command shells will do a file glob expansion of %eli31* before passing the arguments to perl
if you want the script to recieve a literal  '%eli31*' in $ARGV[0] you should quote it
0
 
ozoCommented:
$char = substr($ARGV[0], $i, 1);
        if($char =~ /\% [A-Za-z] /) {
a single character will never match /\% [A-Za-z] / because /\% [A-Za-z] / is 3 characters
0
 
ozoCommented:
$ARGV[0] = '%eli23*';
$process = $ARGV[0];
$process =~ s/\W+//g;
print $process;
#will print
eli23
0
 
Adam314Commented:
What is the rule for taking %eli23* and getting just eli23?  Are you keeping anything that is a letter or number?  Everything except the first and last character?

How are you using eli23?  Are you querying a database using the LIKE operator?  Processing the data in perl using grep?
0
 
ozoCommented:
$ARGV[0] = '%test*';
$process = $ARGV[0];
$process =~ s/%//g;
$process =~ s/\*/.*/g;
# test.* can be used as a regular expression to match test_primary and test_primary_1
0
 
bb0812Author Commented:
I have a main file that is read in by the cmd.pl script.  Here's a snippet of the file:
ETF221                   test221          Tst22Fix         TEST_PRIMARY
ETF221                   test221          Tst22Fix         TEST_PRIMARY_2
ELF310                   test310          Eli31Fix0        ELI31PRIMARY
ELF310                   test310          Eli31Fix0        ELI31BACKUP

I have another script called fc.pl which calls in the cmd.pl script, i.e.
./fc.pl %eli31*

Currently when I execute the script it gives me everything.  All I want is any connection that has eli31 on it, or if I type  ./fc.pl %el*, I want to get any connection that starts with el.  The script should get anything between the % and * or if they just enter a %, get anything afterwards.
./fc.pl %test*
./fc.pl %test_primary  should only about test_primary and not test_primary_2.

0
 
Adam314Commented:
So i'm guessing you are using a regular expression to find the matches.  If so, you need to convert the %eli32* to a regular expression pattern.  It appears that % and * should mean match anything.  If so, use this:


my $pattern = $ARGV[0];    #Get pattern from command line
$pattern =~ s/[%\*]/.*;    #Convert to regular expression pattern
 
#You can now use pattern in a regular expression, eg:
#assuming name contains the name you are searching
if($name =~ /$pattern/i) #name should be included.  The i on the end mean ignore case

Open in new window

0
 
ozoCommented:
# type  ./fc.pl '%el*'
# quoting the * so that the command shell will pass it to the per script
$process = shift;
 $process =~/%//g;
 $process =~/\*/.*/g;
 @ARGV=('mainfile');
 while( <> ){
   print if /\b$process\b/;
}
0
 
bb0812Author Commented:
My server has crashed, and now I have to be rebuilt, once I rebuild I will let you know how testing went with the above solutions.
0
 
Adam314Commented:
Just noticed a typo on my previous post... line 2 should have been
$pattern =~ s/[%\*]/.*/g;    #Convert to regular expression pattern

Open in new window

0
 
bb0812Author Commented:
Besides going on vacation, I finally recovered the server, and now it's working as it's suppose to be.  I tried both solutions to no avail.  I'm pretty sure my question is misleading, so I'll re-write it.

I have a script called fc.pl that calls in the cmd.pl script.  The cmd.pl script goes into an internal program that retrieves the connection information I need once the application is started.  If the application is not up the cmd.pl will state ERROR: TCP Error - Can't connect to..  which works just fine.
Now, the issue is this.  The script works fine but it has a kink on it.  

i.e.  When I execute ./fc.pl %eli31*, I get the following output which gives me everything.  I don't want everything, I just want anything with eli31 on it.  The $proc variable on the script is what gives me the names of connections that I need, that's line 173.

>   ./fc.pl %eli31*
Command: fc.pl -s test310:19018 '@fc '

        Client: /ELF310      Node: test310
        ProcName: Eli31Fix0    

         CONNECTIONS
+----------------------+--------------+--------------+-----------+-----------+-+
|   Connection Name    |  API State   |  Fix State   |  Rx Msgs  |  Tx Msgs  | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31PRIMARY           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP          | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP2           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI23PRIMARY    | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| TEST_PRIMARY     | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| TEST_PRIMARY_2     | DisConnected | DisConnected | 000000000 | 000000000 | |

======================================================================

I only want this:
Command: fc.pl -s test310:19018 '@fc '

        Client: /ELF310      Node: test310
        ProcName: Eli31Fix0    

         CONNECTIONS
+----------------------+--------------+--------------+-----------+-----------+-+
|   Connection Name    |  API State   |  Fix State   |  Rx Msgs  |  Tx Msgs  | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31PRIMARY           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP          | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP2           | DisConnected | DisConnected | 000000000 | 000000000 | |
cmd.pl.txt
0
 
Adam314Commented:
I can't access your attachment.  Can you try attaching again, naming it just cmd.txt.  Maybe the .pl.txt is causing a problem with the server.
0
 
bb0812Author Commented:
File has been re-attached.
cmd.txt
0
 
Adam314Commented:
So it looks like the pattern checking is done on line 172.  Is this correct?  If so, try this for debugging

...
foreach my $arg (@inputParams) {
 
    print "**DEBUG: Processing arg '$arg'\n";
    my $rplStr = "";
 
    $cmdKeys[$i] = [];
 
    if ($arg =~ /%(.+)/) {
 
        print "**DEBUG: arg begins with \%: $1\n";
        $rplStr = "$1";
 
        $rplStr =~ s/\?/./g;
 
        $rplStr =~ s/\*/.*/g;
 
        print "**DEBUG: rplStr='$rplStr'\n";
        
 
        print "**DEBUG: Processing everything in \@procList\n";
        foreach  $proc (@procList) {
 
            print "**DEBUG:     Processing proc '$proc'\n";
            if ($proc =~ /^${rplStr}$/i) {
 
                print "**DEBUG:         Matches!\n";
                push (@{$cmdKeys[$i]}, $ctrl{$proc . "_uniqueName"});
 
                print "This is my connection name $proc\n";
 
            }
        
 
        ##)# foreach my $proc (keys(%ctrl)) (
 
        }# for  $proc (keys(%ctrl)) {
        my $cnt = @{$cmdKeys[$i]};
        if (! $cnt) {
            print "No Matching Process\n";
            @cmdKeys = [];
        }
    } else {
        push (@{$cmdKeys[$i]}, $arg." ".$proc);
    }# if
    
    ++$i;
}# foreach my $arg (@inputParams)
...

Open in new window

0
 
bb0812Author Commented:
Adam314,
The debug statements worked, but my issue is that when I type ELI31 all I want is the connections that start with ELI31, and I want it to ignore everything else.

**DEBUG:  Processing arg '@fc'
**DEBUG:  Processing arg '%ccg*'
**DEBUG:  arg begins with %: ccg*
**DEBUG:  rplStr='ccg.*'
**DEBUG:  Processing everything in @procList
**DEBUG:  Processing proc 'PROCESS'
**DEBUG:  Processing proc '---------------'
**DEBUG:  Processing proc 'TEST_SYSTEM'
**DEBUG:  Processing proc 'TEST_SYSTEM2'
**DEBUG:  Processing proc 'ELI31PRIMARY'
**DEBUG:  Matches!
This is my connection name ELI31PRIMARY
**DEBUG:  Processing proc 'ELI31BACKUP'
**DEBUG:  Matches!
This is my connection name ELI31BACKUP
**DEBUG:  Processing proc 'ELI31BACKUP2'
**DEBUG:  Matches!
This is my connection name ELI31BACKUP2
**DEBUG:  Processing proc 'TEST_PRIMARY'
**DEBUG:  Processing proc 'TEST_PRIMARY_2'
0
 
ozoCommented:
Do you mean when you type %ELI31*  ?
Where did %ccg* come from?
0
 
bb0812Author Commented:
I cut and pasted pieces of the wrong screen.  Yes, everything has to be %ELI31*
On another note, I found that the $kw variable holds %eli31*,  and the @resp holds the entire output, which includes TEST_SYSTEM, TEST_PRIMARY, etc...  How do I match $kw to just print out anything with eli31, note:  I don't need the % nor the *.  Can I accomplish this with a match of $kw?

        if (($exitFlag == 0) && (@inputParams > 0)) {
                my $kw = $inputParams[1];
                $kw =~ tr/a-z/A-Z/;
                if (($kw eq "QUIT") || ($kw eq "EXIT")) {
                        $exitFlag = -1;
                } else {
                        my @resp = &processInputParams;
print "*******DEBUG:  what is kw KW KW KW $kw\n";
                        foreach (@resp) {
                                print "$_";
                        }
                }
        }#if (($exitFlag == 0) && (@inputParams > 0))
0
 
ozoCommented:
WHat iwas the debug output when @resp holds the entire output?
It should not be possible to have
**DEBUG:  rplStr='ELI31.*'
**DEBUG:  Processing everything in @procList
**DEBUG:  Processing proc 'TEST_SYSTEM'
**DEBUG:  Matches!

 but if there is another element in @inputParams that is not %ELI31*, then that would create a different @{$cmdKeys[$i]}  list
so could the extra lines have come from a different arg?

0
 
bb0812Author Commented:
Here's a code snippet of where I think my issue lies.  The $kw variable looks for the $inputParams entry which I have it as [1] which contains %eli31*.   [0] just has FC.  The @resp issues the output of the sub processInputParams.

Here's the output:
*******DEBUG:  what is KW %ELI31*
===========DEBUG======  This is my resp @resp
Command:fc.pl -s test310:19018 '@fc '

===========DEBUG======  This is my resp @resp

===========DEBUG======  This is my resp @resp

===========DEBUG======  This is my resp @resp

===========DEBUG======  This is my resp @resp
        Client: /ELF310      Node: test310
===========DEBUG======  This is my resp @resp
        ProcName: Eli31Fix0    
===========DEBUG======  This is my resp @resp

===========DEBUG======  This is my resp @resp

===========DEBUG======  This is my resp @resp

===========DEBUG======  This is my resp @resp
                    CONNECTIONS
===========DEBUG======  This is my resp @resp
+----------------------+--------------+--------------+-----------+-----------+--
------------+--------------+
===========DEBUG======  This is my resp @resp
|   Connection Name    |  API State   |  Fix State   |  Rx Msgs  |  Tx Msgs  |
x Sequence  | Tx Sequence  |
===========DEBUG======  This is my resp @resp
+----------------------+--------------+--------------+-----------+-----------+-
------------+--------------+
===========DEBUG======  This is my resp @resp
| ELI31PRIMARY            | Connected    | Connected    | 000000659 | 000000656 |
00000000659 | 000000000000 |
===========DEBUG======  This is my resp @resp
+----------------------+--------------+--------------+-----------+-----------+-
------------+--------------+
===========DEBUG======  This is my resp @resp
| ELI31BACKUP         | Connected    | Connected    | 000000660 | 000000656 |
00000000660 | 000000000000 |
===========DEBUG======  This is my resp @resp
+----------------------+--------------+--------------+-----------+-----------+-
------------+--------------+
===========DEBUG======  This is my resp @resp
| ELI31BACKUP2           | Connected    | Connected    | 000000660 | 000000656 |
00000000660 | 000000000000 |
===========DEBUG======  This is my resp @resp
+----------------------+--------------+--------------+-----------+-----------+--
------------+--------------+
===========DEBUG======  This is my resp @resp
| TEST_PRIMARY          | Connected    | Connected    | 000000660 | 000000656 | 0
00000000660 | 000000000000 |
===========DEBUG======  This is my resp @resp
+----------------------+--------------+--------------+-----------+-----------+--
------------+--------------+
===========DEBUG======  This is my resp @resp
| TEST_PRIMARY_2          | Connected    | DisConnected | 000000000 | 000000000 | 0
00000000000 | 000000000000 |
===========DEBUG======  This is my resp @resp

#
# User Command Interface
#
my $exitFlag = 0;
$argCnt = @ARGV;
while ($exitFlag == 0) {
        my $cmd = "";
        if (! $argCnt) {
                print "cbscmd > ";
                if (eof(STDIN)) {
                        $exitFlag = -1;
                } else {
                        $cmd = <STDIN>;
                        chomp ($cmd);
                        $cmd =~ s/\s+/ /g;
                        $cmd =~ s/^\s//g;
                        @inputParams = split(/ /,$cmd);
                }# if (length($cmd)) {
        } else {
                @inputParams = @ARGV;
        }# if (! $argCnt) {
 
        if (($exitFlag == 0) && (@inputParams > 0)) {
                my $kw = $inputParams[1];
                $kw =~ tr/a-z/A-Z/;
                if (($kw eq "QUIT") || ($kw eq "EXIT")) {
                        $exitFlag = -1;
                } else {
                        my @resp = &processInputParams;
print "*******DEBUG:  what is KW $kw\n";
                        foreach (@resp) {
print "===========DEBUG======  This is my resp \@resp\n";
                                print "$_";
                        }
                }
        }#if (($exitFlag == 0) && (@inputParams > 0))
 
        if ($argCnt) {
                $exitFlag = -1;
        }
}# while ($exitFlag = 0) {

Open in new window

0
 
Adam314Commented:

#
# User Command Interface
#
my $exitFlag = 0;
$argCnt = @ARGV;
while ($exitFlag == 0) {
        my $cmd = "";
        if (! $argCnt) {
                print "cbscmd > ";
                if (eof(STDIN)) {
                        $exitFlag = -1;
                } else {
                        $cmd = <STDIN>;
                        chomp ($cmd);
                        $cmd =~ s/\s+/ /g;
                        $cmd =~ s/^\s//g;
                        @inputParams = split(/ /,$cmd);
                }# if (length($cmd)) {
        } else {
                @inputParams = @ARGV;
        }# if (! $argCnt) {
 
        if (($exitFlag == 0) && (@inputParams > 0)) {
                my $kw = $inputParams[1];
                $kw =~ tr/a-z/A-Z/;
                my $re = $kw;
                $re =~ s/%//g;
                $re =~ s/\*/.*/;
                if (($kw eq "QUIT") || ($kw eq "EXIT")) {
                        $exitFlag = -1;
                } else {
                        my @resp = &processInputParams;
                        next unless "@resp" =~ /$re/;
print "*******DEBUG:  what is KW $kw\n";
                        foreach (@resp) {
print "===========DEBUG======  This is my resp \@resp\n";
                                print "$_";
                        }
                }
        }#if (($exitFlag == 0) && (@inputParams > 0))
 
        if ($argCnt) {
                $exitFlag = -1;
        }
}# while ($exitFlag = 0) {

Open in new window

0
 
bb0812Author Commented:
Adam,
Below is the output, I'm still getting the entire output.

*******DEBUG:  what is KW %ELI31* what is RE ELI31
Command:fc.pl -s test310:19018 '@fc '
        Client: /ELF310      Node: test310
        ProcName: Eli31Fix0    

         CONNECTIONS
+----------------------+--------------+--------------+-----------+-----------+-+
|   Connection Name    |  API State   |  Fix State   |  Rx Msgs  |  Tx Msgs  | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31PRIMARY           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP          | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI31BACKUP2           | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| ELI23PRIMARY    | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| TEST_PRIMARY     | DisConnected | DisConnected | 000000000 | 000000000 | |
+----------------------+--------------+--------------+-----------+-----------+-+
| TEST_PRIMARY_2     | DisConnected | DisConnected | 000000000 | 000000000 | |

======================================================================
0
 
bb0812Author Commented:
Adam314, I made a change to your suggestion, and I have it working, but I lost my header.  Is there a way I can keep my header.  Attached is the code snippet.  I commented out the next statement and I added the if after the foreach line.  My output now looks like this.

| ELI31PRIMARY           | DisConnected | DisConnected | 000000000 | 000000000 | |
| ELI31BACKUP          | DisConnected | DisConnected | 000000000 | 000000000 | |
| ELI31BACKUP2           | DisConnected | DisConnected | 000000000 | 000000000 | |

I'm missing the following:
Command:fc.pl -s test310:19018 '@fc '
        Client: /ELF310      Node: test310
        ProcName: Eli31Fix0    

         CONNECTIONS
+----------------------+--------------+--------------+-----------+-----------+-+
|   Connection Name    |  API State   |  Fix State   |  Rx Msgs  |  Tx Msgs  | |
+----------------------+--------------+--------------+-----------+-----------+-+

How can I get the header above.


                        my @resp = &processInputParams;
                        ## next unless "@resp" =~ /$re/;
## print "*******DEBUG:  what is KW: $kw what is RE: $re \n";
                        foreach (@resp) {
                if ($_ =~ /$re/) {
##  print "===========DEBUG======  This is my resp \@resp\n";
                                print "$_";
                                 }
 
                        }

Open in new window

0
 
bb0812Author Commented:
Any status on this?  Please help.
0
 
bb0812Author Commented:
Thank you all for your help.  I have figured out how to put the missing header.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

  • 13
  • 8
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now