【问题标题】:sed substitution: substitute string is a variable needing expansion AND contains slashessed 替换:替换字符串是需要扩展的变量并且包含斜杠
【发布时间】:2021-12-18 01:30:07
【问题描述】:

我正在与sed 进行替换,其中替换字符串包含斜杠。这个一般主题之前已经讨论过堆栈溢出。但是,AFAICT,我有一个新的皱纹,之前的问题没有解决。

假设我有一个文件 ENVIRO.tpml,它有几行,其中一行是

Loaded modules: SUPPLY_MODULES_HERE

我想以自动方式将SUPPLY_MODULES_HERE 替换为已加载模块的列表。 (此时,如果有人有比sed 更好的方法,请告诉我!)我在这里的第一个工作是定义一个环境变量并使用sed 将其放入文件中:

> modules=$(module list 2>&1)
> sed "s/SUPPLY_MODULES_HERE/${modules}/" ENVIRO.tmpl > ENVIRO.txt

(需要2>&1,因为module list 将其输出发送到STDERR,原因我无法开始理解。)但是,通常情况下,模块中有斜线。例如

> echo ${modules}
gcc/9.2.0  mpt/2.20

斜杠终止了我的命令,因为sed 无法理解表达式并认为我的替换命令“未终止”。

所以我照常使用其他字符作为命令分隔符:

> modules=$(module list 2>&1)
> sed "s|SUPPLY_MODULES_HERE|${modules}|" ENVIRO.tmpl > ENVIRO.txt

我仍然收到“未终止的 's'”错误。

所以我用单引号代替双引号:

> sed 's|SUPPLY_MODULES_HERE|${modules}|' ENVIRO.tmpl > ENVIRO.txt

现在我没有收到任何错误,但 ENVIRO.txt 中的行看起来像

Loaded modules: ${modules}

不是我所希望的。

所以,AFAICT,我需要双引号来扩展变量,但我需要单引号来使替代分隔符起作用。但我同时需要两者。我怎么得到这个?

更新:下面 Gordon Davisson 的评论触及了问题的根源:“echo ${modules} 可能具有高度误导性”。用 declare -p 检查 $modules 表明它实际上有一个换行符(或更一般地说,某种换行符)。我所做的是添加一个额外的步骤来从变量中提取换行符。有了这种变化,一切正常。另一种方法是说服 sed 用换行符扩展变量并将其替换为文本,但我无法做到这一点。有接盘侠吗?

【问题讨论】:

  • 我认为您“不需要单引号来使替代分隔符起作用”。你的例子似乎对我有用。你用那个实际的例子来测试它吗? modules="gcc/9.2.0 mpt/2.20";echo Loaded modules: SUPPLY_MODULES_HERE | sed "s|SUPPLY_MODULES_HERE|${modules}|" 或者你有不同的场景,模块中有管道?
  • $modules的实际内容是什么? echo ${modules} can be highly misleading,所以试试declare -p modules | LC_ALL=C cat -v
  • 使用双引号和管道的版本没有明显的问题。预先添加echo,删除重定向,然后发布该输出,这样我们就可以看到 sed 试图执行的内容。
  • 如果您的模板需要执行多个替换或更复杂的操作,那么您可以直接使用 PHP 或 ERB (Ruby) 等模板语言。
  • @GordonDavisson 你可能对我的更新感兴趣。

标签: bash sed


【解决方案1】:

sed 不是这里最好的工具,因为使用了正则表达式和分隔符。

最好使用不需要任何正则表达式的awk 命令。

awk -v kw='SUPPLY_MODULES_HERE' -v repl="$(module list 2>&1)" '
n = index($0, kw) {
   $0 = substr($0, 1, n-1) repl substr($0, n+length(kw))
} 1
' file
  • index 函数在 awk 中使用纯字符串搜索。
  • substr函数用于获取搜索关键字前后的子串。

【讨论】:

    猜你喜欢
    • 2018-01-29
    • 1970-01-01
    • 2023-03-20
    • 2019-03-28
    • 1970-01-01
    • 2014-09-17
    • 2016-07-10
    • 1970-01-01
    • 2018-05-08
    相关资源
    最近更新 更多