Grep并忽略前导空格

时间:2015-07-29 19:27:06

标签: regex awk grep

我一直在编写一个脚本来搜索定义的名称,然后获取它们的十六进制值并将它们放在列表中。一旦我有名单,我将尝试搜索" #define [name]"使用-w确保完全匹配,然后awk' {print $ 3}'获取十六进制值。

然而,如果该行类似于

,则它可以工作
a.h:#define [name] 0x000

但如果它与

相似则不起作用
a.h:    #define [name] 0x000

我该如何解决这个问题?我试过这个

grep -nrw "\s*#define[[:space:]]*$p" . --include=*.h | awk '{ print $3 }'

我认为\s*会忽略#define之前的前导空格,但它不会。我做错了吗?

4 个答案:

答案 0 :(得分:1)

如果它是最后一个元素,您可以随时使用

... | awk '{print $NF}'

你也可以在awk中过滤

awk '/#define/{print $NF}'

这将在与" #define"

匹配后打印第二个字段
awk '{for(i=1;i<NF-1;i++) if($i~"#define") print $(i+2)}'

答案 1 :(得分:1)

在Linux上,这可能完美无缺:

grep -Poinr "#define\s+\[.*?\K[0-9a-f]+x[0-9a-f]+" . --include=*.h

答案 2 :(得分:0)

grep仍匹配您想要的行,但行号和#define之间的空格使其成为单独的awk字段。

find -iname '*.[ch]' -exec sed -nse 's/.*\(#define\s*[a-zA-Z0-9_]*\)\(.*\)/\1: \2/p' {} +

如果您希望分别对每个符号的全文运行此搜索,请将[a-zA-Z0-9_]*替换为您的$p。 (一次提取所有定义的列表然后再搜索它会更快。)

我使用sed -s以防您想要添加sed命令来打印行号。您正在使用grep -n,然后使用awk丢弃行号,所以我想您可能正在展示一个如何使用grep输出的简要示例。

您还可以使用GNU grep -o仅打印与您的模式匹配的行部分。然后,不是让您的模式匹配空格,而是grep输出行总是看起来像

number:#define ...
像你的awk命令一样期待。

答案 3 :(得分:0)

让我们把它作为我们的样本输入:

$ cat a.h
other name 0x100
#define name 0x000
    #define name 0x001

使用awk

$ p=name; awk -v v="$p" '$1=="#define" && $2==v{print $3}' a.h
0x000
0x001

如果我们想要求打印值是十六进制数:

$ p=name; awk -v v="$p" '$1=="#define" && $2==v && $3 ~ /^0x[[:xdigit:]]+$/{print $3}' a.h
0x000
0x001

使用sed

$ p=name; sed -nE "s/\s*#define\s+$p\s+([[:xdigit:]]*)/\1/p" a.h
0x000
0x001

如果我们想对我们匹配的内容更加严格:

$ p=name; sed -nE "s/\s*#define\s+$p\s+(0x[[:xdigit:]]*)$/\1/p" a.h
0x000
0x001

awk和前导空格

前导空格的存在并不会改变字段的awk编号:

$ 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