Sed |包含正则表达式的变量会导致无效的引用错误

时间:2015-11-17 10:12:59

标签: regex bash sed escaping

在使用包含正则表达式的变量时,我遇到了sed和back-referencig的问题。 它是用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,w和fs:

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

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

支持扩展RegExps的

perl可以用来代替sed,比如

fw.close();