2

I have a file which contains each users userid and password. I need to fetch userid and password from that file by passing userid as an search element using awk command.

user101,smith,smith@123
user102,jones,passj@007
user103,albert,albpass@01

I am using a awk command inside my perl script like this:

...
...
my $userid = ARGV[0];
my $user_report_file = "report_file.txt";
my $data = `awk -F, '$1 ~ /$userid/ {print $2, $3}' $user_report_file`;

my ($user,$pw) = split(" ",$data);
...
...

Here I am getting the error:

awk:  ~ /user101/ {print , }
awk:  ^ syntax error

But if I run same command in terminal window its able to give result like below:

$] awk -F, '$1 ~ /user101/ {print $2, $3}' report_file.txt
smith smith@123

What could be the issue here?

7
  • 5
    Why do you want to perform awk in perl and not do it with perl? Commented Mar 29, 2020 at 11:05
  • Since awk can perform faster search. Commented Mar 29, 2020 at 11:06
  • $userid and $user_report_file got substituted with their values, so wouldn't $1 $2 and $3 also get substituted? you'll have to escape the $ for those cases Commented Mar 29, 2020 at 11:10
  • 6
    Are you sure shelling out + running awk is faster than running the search from within Perl? Commented Mar 29, 2020 at 11:16
  • 2
    awk's doing "file operations" too. And more since perl has to capture all of its output in a variable... Commented Mar 29, 2020 at 12:47

1 Answer 1

4

The backticks are a double-quoted context, so you need to escape any literal $ that you want awk to interpret.

my $data = `awk -F, '\$1 ~ /$userid/ {print \$2, \$3}' $user_report_file`;

If you don't do that, you're interpolating the capture variables from the last successful Perl match.

When I have these sorts of problems, I try the command as a string first to see if it is what I expect:

my $data = "awk -F, '\$1 ~ /$userid/ {print \$2, \$3}' $user_report_file";
say $data;

Here's the Perl equivalent of that command:

$ perl -aF, -e '$F[0]=~/101/ && print "@F[1,2]"' report_file

But, this is something you probably want to do in Perl instead of creating another process:

  • Interpolating data into external commands can go wrong, such as a filename that is foo.txt; rm -rf /.
  • The awk you run is the first one in the path, so someone can make that a completely different program (so use the full path, like /usr/bin/awk).
  • Taint checking can tell you when you are passing unsanitized data to the shell.

Inside a program you don't get all the shortcuts, but if this is the part of your program that is slow, you probably want to rethink how you are accessing this data because scanning the entire file with any tool isn't going to be that fast:

open my $fh, '<', $user_report_file or die;
while( <$fh> ) {
    chomp;
    my @F = split /,/;
    next unless $F[0] =~ /\Q$userid/;
    print "@F[1,2]";
    last; # if you only want the first one
    }
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @brian. I was looking for that awk command. I think I missed to escape $.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.