0

I'd like to grep text in files using perl regexp and I do that

find ./ -name *.php -print | xargs perl -nle '/standard/ and print $0'

As I found (using google) in the $0 must be the name of executed script, but it contains "-e". How can I get executed scriptname?

2
  • 4
    You are not executing any script, but passing a string directly to perl, which then gets executed. It doesn't have a name, because it is not stored to a file Commented Feb 20, 2012 at 10:31
  • Sorry, you are right. I neeed passed scriptname by xargs in this perl script. Commented Feb 20, 2012 at 10:43

3 Answers 3

5

Programmers substitute long find/grep command-lines with ack. It uses Perl regex, which are more advanced than GNU grep with -P (PCRE) or whatever gimped implementation of regex POSIX grep uses.

ack --php -l '(?<!\$)standard'
  • Automatically recurses.
  • Automatically excludes version control and junk files.
  • Full Perl power.
  • Type aliases for common file extensions instead of shell glob patterns.
  • Command-line options largely compatible with grep, in the example -l prints the matching file names only.
Sign up to request clarification or add additional context in comments.

Comments

2

I assume what you want is to print the file name. If so, use $ARGV.

perl -nle '/standard/ and print $ARGV'

From perldoc -v '$ARGV'

$ARGV   contains the name of the current file when reading from <>.

The -n switch does just this, it puts a while(<>) loop around the program.

However, this will print file names once for each match. If you want to print only once, you can close the file handle, ending the loop for that file.

perl -nle 'if (/standard/) { print $ARGV; close ARGV; }'

5 Comments

Good answer, I'm deleting mine, since this one is more complete
@knittl I thought using grep was a good idea. I just answered the "perl" part of the problem. In fact, couldn't you just use grep -l "standard" instead of the perl one-liner?
grep needs -r to recurse into subdirectories and another grep to filter the result list. Probably a good idea to filter with find beforehand to not grep through lots of files unecessarily
I've revised my answer and edited it to include a working find+xargs+sh+grep-only-solution
@knittl Why grep -q instead of grep -l?
2

Do you want to list all php files, which contain the string standard? If so, I would use grep -r:

grep -r -l 'standard' . | grep '\.php$'

As stated in my comment to your question, there is no script name, because you are not executing a script file. Assuming you want to print the filename which is passed to xargs/perl, use $ARGV[0] to get the first positional parameter to the perl invocation (xargs automatically appends it to the command line).See TLP's answer instead

You should also use find -print0 | xargs -0 to handle files with newlines correctly.


Extending the grep snippet: It's also possible to use grep inside a new shell, after filtering with find:

find . -name '*.php' -print0 | \
  xargs -0 -L1 sh -c 'grep -l "pattern" "$1"' -

xarsg -L1 to only pass a single file name at once to the new shell. grep -l "$1" to print the file name and stop grepping after the first match. - as first parameter to sh is necessary so that $1 will work.


Another edit …

I was thinking way to complicated. The last command can easily be simplified to:

find . -name '*.php' -print0 | xargs -0 grep -l "pattern"

This of course is not as easily extendable as the sh -c version, which can pretty much do anything.

5 Comments

So it was simple example :-) Expression can be like this "(?<!\$)standard" or harder.
What knittl said, I'd use the -e extension (or egrep) to get an extended regex library (still not ful perl compatible regex, but egrep is a lot faster.
Yes, I agree with you, but Extended regexp is POSIX regexp, not perl, and not support expressions mentioned above.
I tried this find ./ -name *.php -print0 | xargs -0 perl -nle '/standard/ and print $1' and nothing to work (
Sorry, should be $ARGV[0], $1 is shell …

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.