【发布时间】: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"'$' 所以不需要双引号(而且,该变量内没有空格)。
-
只是为了确认一下,您确实有一个有效的
sedcmd 的静态字符串版本吗?你能把它包括在问题中吗?祝你好运。 -
您好,刚刚添加。谢谢!
-
很奇怪,只有
\3部分爆炸了。但我没有做足够的 sed 来觉得我会成功调试这个(以及花费的时间)。下面的perl版本有效吗?如果您真的需要代码中的${replaceNQ}功能,那可能会为您节省大量时间。哦,是的,编辑您的问题以包含uname -a和sed --version的输出。它可能在其他环境中工作,然后它可能被归类为错误。祝你好运。