【问题标题】:Sed | Variable containing regex causes invalid reference error赛德 |包含正则表达式的变量导致无效引用错误
【发布时间】:2016-02-18 15:58:39
【问题描述】:

在使用包含正则表达式的变量时,我遇到了 sed 和反向引用的问题。 它是一个用 bash 编写的解析器。在更早的时候,我想使用 sed 将每一行清理为所需的数据:缩进、键和值(冒号分隔)。数据类似于 yaml,但使用了等号。 数据的基本示例:

overview = peparing 2016-10-22
  license= sorted 2015-11-01

我遇到问题的函数在 while 循环中执行逻辑:

function prepare_parsing () {
  local file=$1

  # regex components:
  local s='[[:space:]]*'  \
        w='[a-zA-Z0-9_]*' \
        fs=':'

  # regexes(NoQuotes, SingleQuotes, DoubleQuotes):
  local searchNQ='^('$s')('$w')'$s'='$s'(.*)'$s'$'      \
        searchSQ='^('$s')('$w')'$s'='$s\''(.*)'\'$s'\$' \
        searchDQ='^('$s')('$w')'$s'='$s'"(.*)"'$s'\$'   \
        replace="\1$fs\2$fs\3"

  while IFS="$fs" read -r indentation key value; do
    ...
    SOME CUSTOM LOGIC
    ...
  done < <(sed -n "s/${searchNQ}/${replace}/p" $file)
}

在尝试调用该函数时,我在 \3 中收到已知的无效引用错误:invalid reference \3 on s' command's RHS

为了调试它,在 vars 定义之后,我使用 printf 和 %q 选项打印了它们的值。

printf "%q\n" $searchNQ $searchSQ $searchDQ $replace

获取这些值:

\^\(\[\[:space:\]\]\*\)\(\[a-zA-Z0-9_\]\*\)\[\[:space:\]\]\*=\[\[:space:\]\]\*\(.\*\)\[\[:space:\]\]\*\$
\^\(\[\[:space:\]\]\*\)\(\[a-zA-Z0-9_\]\*\)\[\[:space:\]\]\*=\[\[:space:\]\]\*\'\(.\*\)\'\[\[:space:\]\]\*\\\$
\^\(\[\[:space:\]\]\*\)\(\[a-zA-Z0-9_\]\*\)\[\[:space:\]\]\*=\[\[:space:\]\]\*\"\(.\*\)\"\[\[:space:\]\]\*\\\$
$'\\1\034\\2\034\\3'

也许这就是问题所在,当 shell (bash) 扩展变量时过多的转义序列(例如,它似乎正在转义 *、[]、...)。

如果我将 -r 选项传递给 sed,它可以完美运行,但我必须避免这种情况,因为将执行脚本的系统不会有这个 sed 实现:我必须使用基本 sed。

您对如何将正则表达式存储到变量中并使它们可用于 RHS 上的反向引用有任何想法吗?

适用于以下两种情况:

使用纯正则表达式字符串时:

sed -n "s/^\([[:space:]]*\)\([a-zA-Z0-9_]*\)[[:space:]]*=[[:space:]]*\(.*\)[[:space:]]*\$/\1:\2:\3/p" $file

当我只使用 vars s、w 和 fs 时:

sed -n "s/^\($s\)\($w\)$s=$s\(.*\)$s\$/\1$fs\2$fs\3/p" $file

非常感谢您的帮助!

【问题讨论】:

  • $something 更改为"$something"...(对于$s$w 等...)
  • 我已经尝试过了,但没有解决问题(在单引号之间是非插值字符,在双引号之间:searchNQ='^('"$s"')( '"$w"')'"$s"':'"$s"'(.*)'"$s"'$' 所以不需要双引号(而且,该变量内没有空格)。
  • 只是为了确认一下,您确实有一个有效的sed cmd 的静态字符串版本吗?你能把它包括在问题中吗?祝你好运。
  • 您好,刚刚添加。谢谢!
  • 很奇怪,只有\3 部分爆炸了。但我没有做足够的 sed 来觉得我会成功调试这个(以及花费的时间)。下面的perl 版本有效吗?如果您真的需要代码中的${replaceNQ} 功能,那可能会为您节省大量时间。哦,是的,编辑您的问题以包含uname -ased --version 的输出。它可能在其他环境中工作,然后它可能被归类为错误。祝你好运。

标签: regex bash sed escaping


【解决方案1】:

可以使用支持扩展 RegExps 的 perl 来代替 sed,例如

perl -n -e "s/${searchNQ}/${replace}/; print"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    • 2017-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多