xotix
xotix

Reputation: 530

Search files recursively and get the value matching the pattern

So, I need some console tool (nothing exotic) or php function which does the following. (I don't want to write my own recursive function e.g. using file_get_contents())

I have a dir with several sub-dirs. Some of the file contain something like <?php ech $this->translate('string'); ?> whereas string is always different.

How can i make a pattern which matches the above function and just returns me the string? Atm, I'd go with grep and exec(); and a second regex for getting my string(s). But probably, i can do it event better.

My grep example: grep -r "$this[->]translate('.*')" dir

Little question aside: How does this differ: grep -r foo dir and grep -r foo dir/* ?

Upvotes: 0

Views: 178

Answers (3)

mohit6up
mohit6up

Reputation: 4348

You can get just the 'string' with lookahead and lookbehind assertions: grep -rhoP "(?<=this->translate\(')[^']*(?='\))" dir

Upvotes: 2

brice
brice

Reputation: 25039

  1. Using square brackets defines character classes, while the dollar sign will be interpreted by the shell as a variable. You will have to escape them for your meaning to be correct. I might do it like this:

    echo "<?php echo \$this->translate('string'); ?>" \
      | grep -ho "\$this\s*->\s*translate('.*?')" 
      | sed "s/\$this->translate('\(.*\)')/\1/"
    

    Where \s stands for

  2. The difference between grep -r <pattern> dir and grep -r <pattern> dir/* is somewhat subtle.

    What actually happens when you run grep -r <pattern> dir/* on the command line is that the shell will expend the dir/* argument into a list of directory.

    In essence:

    grep -rho <pat> dir/*
    

    is equivalent to:

    grep -rho <pat> dir/a dir/b dir/c [etc...]
    

    Where 'a', 'b' and 'c' are directories/files. And so grep will recurse into each of those directories and all files in dir, but not dotfiles or dotted directory.

    You are better off with grep -rho <pat> dir, which takes all files into account.

Upvotes: 0

larsks
larsks

Reputation: 312163

Starting with your little question:

How does this differ: grep -r foo dir and grep -r foo dir/* ?

The second example will not search inside child directories of dir starting with a . (because they won't be matched by the glob). So if you a directory that looks like this:

dir/
  .a_dotted_dir/
  a_visible_dir/

The first example will search inside .a_dotted_dir while the second example will not.

How can i make a pattern which matches the above function and just returns me the string?

You can't, with grep by itself. Grep just matches patterns but does not perform any sort of processing on them. You can probably accomplish what you want by listing files that match your search pattern and processing them with sed, something like:

grep -rl "this->translate('.*')" dir |
  xargs sed -n "s/.*this->translate('\([^']*\)').*/\1/p"

Also, note that I've made some changes to your regular expression. [->] does not match ->, and putting $this inside double quotes will end up with the shell replacing $this with an emptystring. You need to drop the $, escape it, or use single quotes.

Upvotes: 1

Related Questions