使用 sed 将文件中的字符串替换为该名称的变量的内容

2024-03-19

我正在尝试使用 sed 将 %XXX% 形式的文件中的模板字符串替换为 shell 脚本中名为 XXX 的变量的值。

例如以下完美运行

sed "s/%user_home%/$user_home/gi"

So if user_home=fred下列,

NameVirtualHost *:80

<VirtualHost *:80>
  ServerName %server_name%

  ErrorLog /var/log/apache2/%user_home%_webapp_error.log
  CustomLog /var/log/apache2/%user_home%_webapp.log common

  DocumentRoot /home/%user_home%/web_app/public
</VirtualHost>

becomes,

NameVirtualHost *:80

<VirtualHost *:80>
  ServerName %server_name%

  ErrorLog /var/log/apache2/fred_webapp_error.log
  CustomLog /var/log/apache2/fred_webapp.log common

  DocumentRoot /home/fred/web_app/public
</VirtualHost>

问题是我想在不明确知道模板字符串及其变量的情况下运行 sed 命令。也就是说,它查找 %XXX%,然后将其替换为 $XXX 的内容,而不关心变量的实际名称是什么。

我知道它与反向引用有关,但我不知道如何使用反向引用的内容作为变量名。

I tried,

sed "s/%\([a-z_]\)%/$(\1)/gi"

但这失败了,因为它似乎是在寻找一个名为 $\1 的变量。


这里的问题是,到了sed命令实际运行(因此当它检索变量名时),sed命令必须已完全组装(包括将 Bash 变量的值替换为替换字符串);所以一切都以错误的顺序发生。

或者,从更高层次来看,问题在于sed不了解 Bash 变量,因此您需要 Bash 提供变量的详细信息,但 Bash 不了解sed替换,因此它无法知道您需要哪些变量的详细信息。

只要您想使用 Bash 变量,解决方法就是使用更多 Bash:您需要在第一次调用之前识别相关的变量名称sed。下面展示了如何做到这一点。


要获取文件中所有变量名称的列表,您可以编写如下内容:

grep -o '%[a-z_][a-z_]*%' FILE | grep -o '[a-z_][a-z_]*' | sort -u

(首先grep获取该形式的所有表达式%...%。第二grep过滤掉百分号;或者你可以使用sed为此,如果您愿意的话。这sort -u消除重复项,因为您只需要列表distinct变量名。)

有了它,你就可以组装一个sed执行所有必要的替换的命令:

sed_args=()
while read varname ; do
    sed_args+=(-e "s/%$varname%/${!varname}/g")
done < <(grep -o '%[a-z_][a-z_]*%' FILE | grep -o '[a-z_][a-z_]*' | sort -u)
sed "${sed_args[@]}" FILE

(注意使用${!varname}意思是“取值$varname作为变量名,并返回该变量的值。”这就是§3.5.3“外壳参数扩展”Bash 参考手册 http://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion称为“间接扩展”。)

您可以将其包装在一个函数中:

function replace_bash_variables () {
    local file="$1"
    local sed_args=()
    local varname
    while read varname ; do
        sed_args+=(-e "s/%$varname%/${!varname}/g")
    done < <(grep -o '%[a-z_][a-z_]*%' "$file" | grep -o '[a-z_][a-z_]*' | sort -u)
    if [[ "${#sed_args[@]}" = 0 ]] ; then
        # if no variables to replace, just cat the file:
        cat -- "$file"
    else
        sed "${sed_args[@]}" -- "$file"
    fi
}

replace_bash_variables OLD_FILE > NEW_FILE

您还可以调整上面的内容来进行逐行处理,这样就不需要读取文件两次。 (这为您提供了更大的灵活性,因为读取文件两次意味着您必须传入实际文件,并且不能(比如说)将其应用于管道的输出。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 sed 将文件中的字符串替换为该名称的变量的内容 的相关文章

  • 如何将长选项与 Bash getopts 内置一起使用?

    我正在尝试解析 tempBash getopts 的选项 我这样调用我的脚本 myscript temp foo bar someFile 这是我用来解析选项的代码 while getopts temp shots o option do
  • 在 shell 脚本中连接命令字符串

    我正在维护一个现有的 shell 脚本 它将命令分配给 shell 脚本中的变量 例如 MY COMMAND bin command dosomething 然后接下来 它通过执行以下操作将 参数 传递给 MY COMMAND MY ARG
  • 如何替换“docker run”命令中的变量值

    我正在使用 bash 脚本并尝试分配指纹值 如下所示 export FINGERPRINT D0 19 C5 80 42 66 56 AC 6F docker run rm i v var run docker sock var run d
  • 如何将命令作为参数传递给 ssh [重复]

    这个问题在这里已经有答案了 我的需要是让这个命令起作用 sshpass p XXXX ssh oStrictHostKeyChecking no email protected cdn cgi l email protection sudo
  • 保存和恢复陷阱状态?管理多个陷阱处理程序的简单方法?

    有什么好的方法可以覆盖bash陷阱处理程序不会永久破坏可能已设置或尚未设置的现有处理程序 动态管理任意陷阱例程链怎么样 有没有办法保存陷阱处理程序的当前状态 以便以后可以恢复 在 Bash 中保存和恢复陷阱处理程序状态 我将提交以下堆栈实现
  • 此 bash 命令在 Makefile 中未正确运行

    在 Makefile 里面我有这样的 release version poetry version cut f2 d echo release version 如果我运行 我的终端中的语句将毫无问题地运行 gt version poetry
  • POSIX SH 构建循环变量,其元素包含空格

    这是我需要的代码 bin sh x1 a1 a2 x2 b1 b2 list SOMETHING for x in list do echo x done 以及我想要的输出 a1 a2 b1 b2 问题是 应该做什么SOMETHING是 我
  • apt-get install tzdata 非交互式

    当我尝试 apt get install y tzdata 将显示用于选择时区的命令行选项 我试图在脚本中使用它来进行一些设置 如何在没有用户输入的情况下使 apt get 运行 我知道重新配置 tzdata 我可以做 echo Ameri
  • 使用 .htaccess 重定向到动态相对路径?

    是否可以使 htaccess 理解 动态相对路径并正确重定向到它们 我的设置如下 http domain com htroot aaa xyz http domain com htroot bbb xyz http domain com h
  • 将“npm run start”的输出写入文件

    我想捕获的输出npm run start在一个文件中 我遇到了大量错误 我想更好地控制如何筛选输出 当我尝试时 npm run start gt log txt 我得到一个非常简短的文件 8 行 其结尾为 34m 39m 90m wdm 3
  • 从 TypeScript 运行任何 Linux 终端命令?

    有没有办法直接从 TypeScript 类中执行 Linux 终端命令 这个想法是做类似的事情 let myTerminal new LinuxTerminal let terminalResult myTerminal run sudo
  • 如何让“grep -zoP”单独显示每个匹配项?

    我有一个此表格的文件 X this is the first match blabla X this is the second match and here we have some fluff 我想提取 X 之后和相同标记之间出现的所有
  • 将字符串分解为标记,保持引用的子字符串完整

    我不知道我在哪里看到它 但是谁能告诉我如何使用 php 和 regex 来完成这个任务 this is a string that has quoted text inside 我希望能够像这样爆炸它 0 this 1 is 2 a 3 s
  • Bash 脚本大小限制?

    我有一个 bash 脚本 在 RHEL 或 OS X 上运行时出现以下错误 第 62484 行 意外标记 换行符 附近出现语法错误 第 62484 行 o gz 这是一个自动生成的脚本 用于解决我公司使用的 Grid Engine 计算集群
  • Java:正则表达式 - 如何获取第一个引用文本

    作为初学者regex我相信我要问的事情太简单了 但无论如何我都会问 希望它不会打扰你帮助我 可以说我有这样的文字 你好 cool1 这个词 cool2 我想获取第一个引用的文本 即 cool1 不带 我的模式应该是什么 当使用匹配器时 我如
  • 在 Fish Shell 中设置导出

    我安装了多个版本的 PHP 对于我的正常开发 我总是使用通过自制程序安装的 PHP 5 5 x 在鱼壳里 which php php version gt usr local bin php gt PHP 5 5 8 cli built J
  • 使用 Python 从网站下载所有 pdf 文件

    我遵循了几个在线指南 试图构建一个可以识别并从网站下载所有 pdf 的脚本 从而避免我手动执行此操作 到目前为止 这是我的代码 from urllib import request from bs4 import BeautifulSoup
  • 使用 sed 删除非字母数字字符

    我正在尝试验证一些输入以删除一组字符 只允许使用字母数字字符加 句点 下划线 连字符 我测试了正则表达式 w here http gskinner com RegExr http gskinner com RegExr 它与我想要删除的内容
  • 为什么这个没有特殊字符的正则表达式会匹配更长的字符串?

    我正在使用此方法来尝试查找匹配项 例如 Regex Match A2 TS OIL TS OIL RegexOptions IgnoreCase Success 我得到了真实的结果 我很困惑 我认为这应该返回 false 因为模式中没有特殊
  • 为什么我不能将 sed 的输出重定向到文件

    我正在尝试运行以下命令 someprogram tee dev tty sed s 2 gt output file 但当我去查看时 该文件始终是空白的 如果我删除 gt output file从命令末尾 我可以看到 sed 的输出 没有任

随机推荐

  • 设置Windows中每个进程的最大CPU使用率[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 有没有办法在 Windows 7 中设置进程的最大 CPU 使用率 您可以查看 Windows Server 2008 R2 和 Windows 7
  • 使用 Windows 窗体在按钮上显示工具提示

    如何使用按钮在按钮上显示工具提示Windows 窗体 http en wikipedia org wiki Windows Forms 工具提示是一个singleWinForms 控件 用于处理显示工具提示multiple单个表单上的元素
  • Spring Boot MVC 的 web.xml 等效吗?

    JSP规范让我可以服务 html使用以下方法将文件作为 JSP 即让容器将它们作为 JSP 文件处理
  • 动态需要 React Native 图像

    我正在努力在我的反应原生项目中加入一些代表国家的旗帜 我发现你不能在 React Native 中动态地要求图像 如下例所示 require assets flags 32 countryCode png 鉴于我发现的如此回应here ht
  • ELB 后面的 Symfony2 重定向到 http 而不是 https

    Issue 用户登录https example com login https example com login 认证已获批准 根据 security yaml 中的配置 Symfony 在登录后将用户重定向到个人资料页面 但它会将它们重
  • CMake工具链包含多个文件

    由于与提及无关的原因 我希望能够将多个文件包含到工具链文件中 假设我的工具链包含以下内容 message STATUS file1 is ok include build file2 file2 包含标识行 message STATUS f
  • 如何将媒体查询添加到 Jquery 中

    是否可以将媒体 jquery 添加到您的 jquery 代码中 当我的屏幕尺寸达到 800px 时 我需要减小 slideWidth 83 document ready function slider4 bxSlider slideWidt
  • 如何生成CMakeLists.txt?

    我需要一些关于如何为 CMake 自动生成 CMakeLists txt 文件的指示 建议 有谁知道现有的发电机吗 我已经检查了列出的CMake 维基 http www cmake org Wiki CMake Basic CMakeLis
  • jQuery - 如何检查元素是否具有这些类中的任何一个

    Example 如何检查 div test 是否有以下任一内容 a1 a2 a3 a4 a5课程 只有一个 if 语句 div class a1 a2 a5 div 你可以使用jQuery is功能 http api jquery com
  • 将恐慌重定向到指定的缓冲区

    有什么办法可以做到这一点吗 在终端图形库中 如果发生异常 异常将在显示之前被刷新 这使得使用该库进行编程非常困难 impl Drop for Terminal fn drop mut self self outbuffer write al
  • 在 Objective-C 中双击打开文件

    我想在双击文件时使用我的应用程序打开该文件 我已在应用程序中注册了文件类型 并且application openFile 如果我将文件拖放到应用程序图标上 方法就可以正常工作 在苹果文档中 它说 当用户双击文件时 此方法也应该起作用 我看到
  • UIDatePicker 15 分钟增量 Swift

    In swift 我想知道如何使用我的UIDatePicker选择 15 分钟增量 因此 我不想选择 60 分钟的小时 而是只希望能够选择 00 分钟 15 分钟 30 分钟和 45 分钟 这是我当前的实现 var schedulePick
  • Javascript 在元素上切换类

    假设我有这个 HTML 结构 div class sType click div class Switcher span class customText Custom text span div div div class sType c
  • 使用 babel 递归地转译服务器文件

    我的文件夹结构是这样的 functions dist private server controllers middleware clientAuth js someOtherAuth js index js model js router
  • Highcharts 日期相差一天

    我以毫秒为单位传递 x 轴 然后将 x 轴定义为 xAxis type datetime 然而 Highcharts 似乎没有在 x 轴上获得准确的日期 而是相差一天 为了说明这一点 将鼠标悬停在任何条形图上 在这篇文章的底部拨弄 您将看到
  • mockito 的学习资源 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我需要使用mockito为现有代码创建单元测试框架 我找不到一个开始学习 Mockito 的好地方 你能给我推荐一个很好的mockito学
  • 在缓存图像上触发 load() 事件的更好方法是什么?

    我正在编写一个脚本 该脚本等待隐藏内容加载div在激活指向它的缩略图之前 preload img first child bind load activateThumb each function if this complete this
  • 如何获取属性的串联值?

    XPath 表达式 div concat id class 失败并出现错误 The expression is not a legal expression 在 Firefox 25 0 中 来自用户脚本 为什么 以及如何解决 对于输入 d
  • 如何通过 MediaWiki API 从 Wikipedia 文章中获取信息框? [复制]

    这个问题在这里已经有答案了 维基百科文章可能有信息框模板 通过以下调用 我可以获得包含信息框的文章的第一部分 http en wikipedia org w api php action parse pageid 568801 sectio
  • 使用 sed 将文件中的字符串替换为该名称的变量的内容

    我正在尝试使用 sed 将 XXX 形式的文件中的模板字符串替换为 shell 脚本中名为 XXX 的变量的值 例如以下完美运行 sed s user home user home gi So if user home fred下列 Nam