【问题标题】:AWK regular expression compile failedAWK 正则表达式编译失败
【发布时间】:2021-05-18 05:40:26
【问题描述】:

当我尝试运行这个项目时https://github.com/taviso/loadlibrary/ 主要用于Linux下运行windows defender

我在genmapsym.sh 中遇到了一个问题,它假设从.map 文件生成符号。

genmapsym.sh 包含以下代码:

awk 'BEGIN { printf ".macro symbol name, address\n.set \\name, \\address\n.func \\name\n.endfunc\n.endm\n" }

    /Publics by Value/,/Program entry point/ {

        if (gsub(/^ ....:/,"'${1}'+0x")) {
            gsub(/[\"/^}{\[\]$?:@()><`\'\''|~,=!+&*-]/, "_",$2);
            printf "symbol %s,%s\n",$2,$1
        }
}' | as -o ${2} -gstabs+ --32

每当我尝试运行它以获取gdb 中的符号时,我都会收到此错误

gdb> shell bash genmapsym.sh 0x5a100000+0x1000 symbols_3383.o < engine/mpengine.map
awk: line 6: regular expression compile failed (bad class -- [], [^] or [)
[\"
awk: line 6: missing ) near }
awk: 6: unexpected character '\'
awk: line 6: syntax error at or near [
awk: line 6: extra ')'

在项目 repo 中有一条我无法理解的注释:

请注意,genmapsym.sh 假定您使用的是 GNU awk。

因为我不知道我在默认情况下在 bash 中使用什么,或者至少不知道如何确定哪个是默认设置。

我的环境是:

Linux ubuntu 5.4.0-65-generic #73~18.04.1-Ubuntu SMP 2021 x86_64 x86_64 x86_64 GNU/Linux
awk version: mawk 1.3.3 

我该如何解决这个问题,以便它可以在我的环境中正常运行。

【问题讨论】:

  • awk --version之后输出什么?
  • awk 不支持该命令,但我使用了awk -W version,即mawk 1.3.3 @Daweo
  • 好吧,那就这样吧。您正在使用具有不同 awk 的 GNU awk 特定代码。
  • 该代码没有使用任何 gawk 特定的功能,而是依赖 gawk 比其他 awk 更能容忍其错误。 YMMV - 你最好只修复错误,这样它就可以在任何 awk 中工作,包括可能决定不再容忍的 gawk 的未来版本。

标签: regex ubuntu awk


【解决方案1】:

您的主要问题是 gsub() 中使用的这个正则表达式:

/[\"/^}{\[\]$?:@()><`\'\''|~,=!+&*-]/

问题 1: 看到\'\''了吗?我猜想是'\''\\'\''

您的 awk 脚本由 's 分隔:awk 'BEGIN ... }' | ...。在 shell 中,' 不能在 '-delimted 字符串中包含,包括在脚本中。一种解决方法是在字符串内部使用'\'',因为第一个' 提供字符串结束分隔符,\' 在字符串外部提供',然后最后一个' 提供新的开始-of-string 分隔符。

因此,您不能编写其中任何一个来获得介于 foobar 之间的 '"

'foo'bar'
'foo\'bar'

但你可以写:

'foo'\''bar'

在 awk 中,您也可以将 ASCII 八进制代码用于 '

'foo\047bar'

它的优点是无论脚本是存储在文件中还是在命令行中使用,它都可以工作。

问题 2: 看到 \] 了吗?这不符合 POSIX 标准,因此任何 awk 的任何版本都可以使用 YMMV。要在括号表达式中获取],它必须是括号表达式中的第一个非^ 字符。因此,为了方便所有 awk,不要写 [x\]y],而是写 []xy]

问题 3: 除了 gsub() 中的正则表达式之外,您的其他 gsub() 的替换文本存在问题:"'${1}'+0x"。这不是您将 shell 变量的值传递给 awk 脚本的方式,因为它使 shell 变量扩展为脚本的一部分,并使其值对 shell 的解释开放,因此会导致各种潜在的神秘错误和安全性问题。将 shell 变量的值作为 awk 变量传递给 awk - 请参阅 how-do-i-use-shell-variables-in-an-awk-script

所以,而不是:

awk 'BEGIN { printf ".macro symbol name, address\n.set \\name, \\address\n.func \\name\n.endfunc\n.endm\n" }

    /Publics by Value/,/Program entry point/ {

        if (gsub(/^ ....:/,"'${1}'+0x")) {
            gsub(/[\"/^}{\[\]$?:@()><`\'\''|~,=!+&*-]/, "_",$2);
            printf "symbol %s,%s\n",$2,$1
        }
}'

您应该使用它进行最小的更改以使其正常工作:

awk -v num="$1" 'BEGIN { printf ".macro symbol name, address\n.set \\name, \\address\n.func \\name\n.endfunc\n.endm\n" }

    /Publics by Value/,/Program entry point/ {

        if (gsub(/^ ....:/,num"+0x")) {
            gsub(/[]["/^}{$?:@()><`'\''|~,=!+&*-]/, "_",$2);
            printf "symbol %s,%s\n",$2,$1
        }
}'

我还从括号表达式中删除了一些不必要的转义(例如,您不需要\",只需",根据您的 awk 版本,这也会产生警告或错误消息)。

范围表达式 (/Publics by Value/,/Program entry point/) 通常是个坏主意,顺便说一句 - 我会使用标志来代替,请参阅 is-a-start-end-range-expression-ever-useful-in-awk

【讨论】:

  • @rowboat 我对此表示怀疑,但如果您有,请尝试并告诉我们。
  • 很高兴知道。它甚至不会用 gawk --traditional--lint--posix 发出警告,所以我猜这不符合 POSIX。
【解决方案2】:

使用了 awk -W 版本,即 mawk 1.3.3

这不符合要求

您正在使用 GNU awk

AWK 确实有 various implementations,您尝试运行的项目需要 GNU AWK(也称为 gawk),同时您提供 Michael Brennan 的实现 (mawk)。

【讨论】:

  • 知道如何解决这个问题,因为我正在使用可供下载的最新版本的 ubuntu。
  • 下载 gawk 后是否有任何其他指令使其成为 bash 中的默认值?
  • @alex 我不熟悉 bash 或 ubuntu,所以我可能只建议您阅读有关 PATH 变量的信息。
  • @alex:确保安装了gawk 包,并明确使用gawk。或者在 Debian/Ubuntu 系统上,您可以使用 sudo update-alternative awk 来设置哪个 awk 是 /usr/bin/awk
猜你喜欢
  • 1970-01-01
  • 2018-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
  • 2018-01-04
相关资源
最近更新 更多