Reputation: 9
I've been working on a script to search for names of defines, and then grab the hex values for them and put them in the list. Once I have the list of names I'll attempt to search for "#define [name]" using -w to ensure exact match, and then awk '{ print $3 }' to grab the hex value.
However it works if the line is similar to
a.h:#define [name] 0x000
But it does NOT work if it is similar to
a.h: #define [name] 0x000
How can I get around this? I have tried this
grep -nrw "\s*#define[[:space:]]*$p" . --include=*.h | awk '{ print $3 }'
I thought the \s*
would ignore the leading whitespace before #define
but it doesn't. Am I doing something wrong?
Upvotes: 0
Views: 4805
Reputation: 67567
If it's the last element, you can always use
... | awk '{print $NF}'
You can also filter in awk as well
awk '/#define/{print $NF}'
This will print the second field after a match with "#define"
awk '{for(i=1;i<NF-1;i++) if($i~"#define") print $(i+2)}'
Upvotes: 1
Reputation: 113984
Let's take this as our sample input:
$ cat a.h
other name 0x100
#define name 0x000
#define name 0x001
$ p=name; awk -v v="$p" '$1=="#define" && $2==v{print $3}' a.h
0x000
0x001
If we want to require that the printed value is a hex number:
$ p=name; awk -v v="$p" '$1=="#define" && $2==v && $3 ~ /^0x[[:xdigit:]]+$/{print $3}' a.h
0x000
0x001
$ p=name; sed -nE "s/\s*#define\s+$p\s+([[:xdigit:]]*)/\1/p" a.h
0x000
0x001
If we want to be a bit more strict about what we match:
$ p=name; sed -nE "s/\s*#define\s+$p\s+(0x[[:xdigit:]]*)$/\1/p" a.h
0x000
0x001
The presence of leading spaces does not change how awk numbers a field:
$ echo ' 1 2' | awk '{for (i=1;i<=NF;i++)printf "field %s = %s\n",i,$i;}'
field 1 = 1
field 2 = 2
$ echo '1 2' | awk '{for (i=1;i<=NF;i++)printf "field %s = %s\n",i,$i;}'
field 1 = 1
field 2 = 2
Upvotes: 0
Reputation: 469
On linux this may work perfectly:
grep -Poinr "#define\s+\[.*?\K[0-9a-f]+x[0-9a-f]+" . --include=*.h
Upvotes: 1
Reputation: 365781
grep
still matches the lines you want, but the whitespace between the line number and the #define
makes it a separate awk
field.
find -iname '*.[ch]' -exec sed -nse 's/.*\(#define\s*[a-zA-Z0-9_]*\)\(.*\)/\1: \2/p' {} +
Replace [a-zA-Z0-9_]*
with your $p
, if you want to run this search over the full text for every symbol separately. (It'd be faster to extract a list of all the defines once, and then search it.)
I used sed -s
in case you want to add a sed command to print the line number. You were using grep -n
and then throwing away the line number with awk, so I figured maybe you were showing a cut-down example of how you really use the grep
output.
You could also use GNU grep -o
to print only the part of the line that matches your pattern. Then instead of having your pattern match whitespace the grep output lines will always look like
number:#define ...
like your awk command is expecting.
Upvotes: 0