4

I often need to run some Perl one-liners for fast data manipulations, like

some_command | perl -lne 'print if /abc/'

Reading from a pipe, I don't need a loop around the command arg filenames. How can I achieve the next?

some_command | perl -lne 'print if /$ARGV[0]/' abc

This gives the error:

Can't open abc: No such file or directory.

I understand that the '-n' does the

while(<>) {.... }

around my program, and the <> takes args as filenames, but doing the next every time is a bit impractical

#/bin/sh
while read line
do
   some_command | perl -lne 'BEGIN{$val=shift @ARGV} print if /$val/' "$line"
done

Is there some better way to get "inside" the Perl ONE-LINER command line arguments without getting them interpreted as filenames?

Snorri
  • 446
  • 2
  • 10
kobame
  • 5,766
  • 3
  • 31
  • 62
  • Why do so many people (not just this poster) get hung up on 'Perl one-liners'? They're great when they work, but they're not compulsory; multi-liners work too. – Jonathan Leffler May 13 '13 at 14:39
  • @JonathanLeffler Hm.. it is not about one line vs two lines. I can make multilne script with multiple `-e`. But it is about not making unnecessary files with script sources. Me many-many times uses oneliners, simply because they're FAST way to do some powerfull things directly from a command line without editing an script file... Maybe for you is OK make an script file for 2 line script - for me is faster write it directly into command line... ;) :) – kobame May 13 '13 at 14:46
  • @Jonathan, I administer thousands of servers. A one-liner I can paste into ssh, can stick into a series of piped commands I'm passing some logs through, can communicate quickly and fully to someone in chat, etc. And what I've done is more obvious in bash history than a two-step vi/GET--./mysecretskript. And with a one-liner I'm rarely lured away from my real task. And I'm rarely tempted to install Perl modules onto a random server when they may not be needed by anything else. And I rarely find that I've built a giant library of never-useful-again, undocumented, mysteriously-named scripts. – Julian Fondren May 13 '13 at 16:07
  • And Perl's humble. Just look at `perldoc perlrun`, or some of the odd members of `perldoc perlvar`. This is not a language born of a community that thought it too cool to be useful at the commandline. (I guess those people just use a lot of bash, sed, and awk.) – Julian Fondren May 13 '13 at 16:10

3 Answers3

5

Also reasonably short:

... | expr=abc perl -lne 'print if /$ENV{expr}/'

Works in bash shell but maybe not other shells.

mob
  • 117,087
  • 18
  • 149
  • 283
  • Sneaky. Works with POSIX-based shells (Bourne, Korn, ... — and Bash as noted), but not with C shell derivatives. But that's OK; sea shells should be left on the seashore and not used for scripting. – Jonathan Leffler May 13 '13 at 15:03
  • @JonathanLeffler Since when is goode olde bourne a POSIX-based shell? – Adrian Frühwirth May 13 '13 at 21:37
  • @AdrianFrühwirth: it's a shorthand — Bourne shell supports the notation, and is the basis for the POSIX shell. So it should be 'Bourne-based shells' and then list some variants...I didn't think I was going to get called on it. – Jonathan Leffler May 13 '13 at 21:39
  • @JonathanLeffler Didn't mean to be nitpicky (OK, maybe a bit), and I highly enjoyed the csh remark. No offence intended. – Adrian Frühwirth May 13 '13 at 21:43
5

Some solutions:

perl -e'while (<STDIN>) { print if /$ARGV[0]/ }' pat

perl -e'$p = shift; while (<>) { print if /$p/ }' pat

perl -e'$p = shift; print grep /$p/, <>' pat

perl -ne'BEGIN { $p = shift } print if /$p/' pat

perl -sne'print if /$p/' -- -p=pat

PAT=pat perl -ne'print if /$ENV{PAT}/'

Of course, it might make more sense to create a pattern that's an ORing or all patterns rather than executing the same command for each pattern.

ikegami
  • 367,544
  • 15
  • 269
  • 518
2

It depends on what you think will be in the lines you read, but you could play with:

#/bin/sh
while read line
do
   some_command | perl -lne "print if /$line/"
done

Clearly, if $line might contain slashes, this is not going to fly. Then, AFAIK, you're stuck with the BEGIN block formulation.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Using double quotes will expand the `$_` variable too (the last arg of the last bash command). The `$_` is pretty common in my oneliners. ;) But, thanx anyway for the suggestion - good point. :) – kobame May 13 '13 at 14:58
  • 1
    You certainly have to review the code case by case, and using double quotes around the program in the argument to `-e` is generally more dangerous than using single quotes. You'd have to use `\$` to protect `$`, etc. In this specific context, it works without those complications; for anything much more complex, I'd probably go with single quotes and a BEGIN block. – Jonathan Leffler May 13 '13 at 15:00