How do i find "&variable[0]" using grep -r?

Guys,

i've got hundreds of C programs in my ~/devel/ directory and sub-directories. is there a way i can use grep -r followed by some zsh, sh, bash, to find some code that starts with "&foo[N]" or something similar?

thanks in advance!

find . -name *.c | xargs grep '&foo[N]'

What is "something similar"?
And, what do you mean by "starts with"? First line in file, or first chars in some line in that file.

find . -name *.c | xargs grep '&foo[N]'

brought xargs to mind. but two things here:

  1. will your find clause get me only my .c files? [i hope, i hope]
  2. will [A-Za-z] or somesuch work to replace "foo"?

basically, i'm looking for anunknown variable that is prepended with "&" and
ends with [N]. N is most likely 0.

thanks.

How about

grep -Eri "\&[[:alpha:]]{1,3}\[[0-9]\]" *.c

the ampersand is the first byte in the variable. it is an array that starts {probably} at 0.

---------- Post updated at 02:26 PM ---------- Previous update was at 02:08 PM ----------

Yes! probably this kind of voodoo may do the trick. A day ago, a guy i've known for many years shows me how-to copy a string array into a Global variable that i may use [or may NOT] use. his code is old and needs a few tweaks. no problem. i am trying to understand how the file foo.16.text can be copied into (global) char *GtkLabelBar[256];

but before i just-do-it, i need to understand why his example works. i have found many ancient examples; want to print them out so i can get some clues.

Once i see it, i'll continue.

Note that grep -r statement will not find *.c files in subdirectories. The find statement will also fail to do that if the are any *.c files present in the current directory . In both cases *.c is expanded by the shell and the the result is provided as parameters to the command. To find all *.c files *.c needs to be quoted:

find . -name '*.c' -exec grep -E '&[[:alpha:]]+\[[0-9]+\]' {} +

Another thing is that xargs will break things if there are spaces in the filename. The example shows how it could be done without xargs, by using -exec . The + sign makes it at least as efficient as xargs

Note that with either find ... -exec ... + or with xargs , if only one matching file is found or if there are enough matching files to invoke grep multiple times and the last invocation only passes one filename to grep , the filename will not be printed along with the matching line. To protect against this rare case, add another file operand that you know will never match your pattern:

find . -name '*.c' -exec grep -E '&[[:alpha:]]+\[[0-9]+\]' /dev/null {} +

Does any of your code contain array variables with underscores or digits in their names? If so, maybe you want:

find . -name '*.c' -exec grep -E '&[_[:alpha:]][_[:alnum:]]*\[[0-9]+\]' /dev/null {} +
1 Like

Hi Don, originally I wanted to expand my post with something similar (using -H if the user's grep supports it). With /dev/null option I worried that if the ARG_MAX would be reached with that xargs or + option, ARG_MAX might become exceeded when those arguments are fed to grep together with /dev/null . What are your thoughts on this?

I also did a small test with only one file and I found this, using OSX:

$ cat testdir/infile1
x
$ grep x ./testdir/infile1 
x
$ find . -name 'i*1' | xargs grep 'x'
./testdir/infile1:x
$ find . -name 'i*1' -exec grep 'x' {} +
./testdir/infile1:x
$ find . -name 'i*1' -exec grep 'x' {} \;
x

So it would seem that somehow the /dev/null precaution is only necessary when using \;

--EDIT--
Nevermind about that last bit, it seems this is not common behaviour , on other OS it does not print the file name, so this appears to be implementation specific.

According to the standards, grep is not allowed to print the name of the matched file unless two or more file operands are specified; and is required to print the name of the matched file if two or more file operands are specified. (The standards do not specify the -H option, but that is an allowed extension.)

find ... -exec ... + and xargs are required by the standards to limit the command line length such that when the command is invoked, the combined argument and environment lists shall not exceed {ARG_MAX} bytes. Of course, if the environment, fixed arguments, and one pathname exceed {ARG_MAX}; neither find nor xargs will be able to invoke any commands. And, with some options, xargs is also constrained by {LINE_MAX}.

1 Like