我想用该文件中的另一个路径替换 yml 文件中的路径

Posted

技术标签:

【中文标题】我想用该文件中的另一个路径替换 yml 文件中的路径【英文标题】:i want to replace a path inside a yml file with another path in that file 【发布时间】:2021-01-17 00:19:50 【问题描述】:

我尝试使用 sed 命令替换 yml 文件中的路径,并尝试注释该文件中的旧路径。评论工作正常,但不是专门针对该路径。该文件中还有其他路径。我的 yml 文件如下所示:

  enabled: true
  close_eof: true
  #close_inactive: 1h
  paths:
      - /home/directory/another_directory/directory_20200910/*_*_*

现在我希望我的文件看起来像

  enabled: true
  close_eof: true
  #close_inactive: 1h
  paths:
      - /home/directory/another_directory/directory_(today's date here-20201001)/*_*_*

请注意:yml 文件有四个空格,路径前有一个“-”

SPTH='/home/directory/another_directory'
sed -e '/$SPTH/ s/^#*/#/' -i test.yml
echo - /home/directory/another_directory/directory_date +%Y%m%d >> /home/test.yml

但这似乎不起作用,另一件事是尝试过的是

sed -e '/home/ s/^#*/#/' -i test.yml
echo - /home/directory/another_directory/directory_`date +%Y%m%d` >> /home/test.yml

这很好用,但它会在每个以/home 开头的路径上添加注释,并且还会在文件末尾回显路径。因此我必须使用 sed 的东西,因为我想用当前日期替换路径。

如果我想用昨天的日期替换文件夹的日期,请告诉我,因为我想在文件夹创建一天后运行脚本。

【问题讨论】:

YAML 工具需要使用像 yq 这样的语法感知解析器进行解析。你能安装这样的工具吗? - mikefarah.gitbook.io/yq 我没有尝试安装,我试图使用 sed 直接替换它而不解析 【参考方案1】:

我发现有几个问题:

这个正则表达式首先应该做什么?

正则表达式/home/ s/^#*/#/ 将对所有包含home 的行执行替换(很酷),但它会将行开头的任意数量的# 替换为单个#

即:它将删除每一行开头的所有#,然后在每一行添加一个新的(因为^#* 也将匹配零个前导哈希)。

这可能不是你想要的。

单引号会阻止变量的扩展

sed -e '/$SPTH/ s/^#*/#/' 将对包含文字 $SPTH 的所有行执行替换(无论是否存在 shell 变量 SPTH 以及它的内容是什么)。

这可能不是你想要的。

如果要扩展 $SPTH,则需要双引号 (")

(当然,你会遇到问题,因为 $SPTH 的扩展值包含斜杠,会干扰 sed 表达式本身)。

解决方案。

要简单地替换当前目录,请使用以下内容:

SPTH='/home/lt-1027'
sed \
  -e "s|^\( *-  *$SPTH\)/.*/\*_\*_\*|\1/$(date +%Y%m%d)/*_*_*|" \
  -i test.yml

这使用管道| 作为分隔符,以避免$SPTH 中的斜线出现问题。 它将文件的缩进、破折号和开头(直到$SPTH 的结尾)捕获到捕获组\1 中,然后用于替换,因此替换文本具有与原始文本相同的缩进(希望保持你的 yaml 完好无损)

如果您想保留原始路径并将其注释掉,请使用

sed \
  -e "s|^\(\( *-  *$SPTH\)/.*/\*_\*_\*\)$|#\1\n\2/$(date +%Y%m%d)/*_*_*|" \
  -i test.yml

这会将整个旧行捕获到引用 \1 中(因此我们可以通过前缀 # 将其替换为自身的注释掉版本);缩进现在被捕获到\2)

【讨论】:

您可以在替换中使用&,而不是为整行添加额外的捕获组。【参考方案2】:

对 YAML 使用简单的文本处理工具并不总是正确的。如果您知道您的 YAML 输入将始终具有某种格式,那么这样的解决方案可能是可以接受的。

假设您要替换 所有出现

/home/directory/another_directory/directory_<any_number>/*_*_*

/home/directory/another_directory/directory_<today_s_date>/*_*_*

你可以使用

sed -e 's#\(/home/directory/another_directory/directory_\)[0-9]*\(/\*_\*_\*\)#\1'$(date +%Y%m%d)'\2#' test.yml

使用您的示例输入打印出来

enabled: true
close_eof: true
#close_inactive: 1h
paths:
    - /home/directory/another_directory/directory_20201001/*_*_*

当然您可以使用选项-i 来替换输入文件,而不是打印修改后的数据。 (确保sed 命令正常工作,因为您可能会丢失原始输入数据。)

如果需要变量SPTH中的路径,可以这样修改脚本

SPTH='/home/directory/another_directory'
sed -e 's#\('$SPTH'/directory_\)[0-9]*\(/\*_\*_\*\)#\1'$(date +%Y%m%d)'\2#' test.yml

如果你想用昨天的日期而不是今天的日期,只需替换

date +%Y%m%d

date -d yesterday +%Y%m%d

此选项-d 未由 POSIX 标准定义,但在 Linux 上可用于 GNU date

【讨论】:

【参考方案3】:

你可以试试:

date +%Y%m%d
20201001
today=$(date +%Y%m%d)
sed "s#/directory_[0-9]*#/directory_$today#" test.yml

输出:

enabled: true
close_eof: true
#close_inactive: 1h
paths:
    - /home/directory/another_directory/directory_20201001/*_*_*

使用带有选项 -i 的 sed 来保存输出

【讨论】:

谢谢。我快到了。你能告诉我是否想在同一个脚本中将日期更改为昨天,这怎么可能?因为我将在创建该日期文件夹的一天后运行脚本 我自己实现了谢谢。我做了date -d "yesterday" +%Y%m%d yesterday=$(date -d "yesterday" +%Y%m%d)

以上是关于我想用该文件中的另一个路径替换 yml 文件中的路径的主要内容,如果未能解决你的问题,请参考以下文章

用bash中的另一个文件替换整个文件

编辑时如何用导航控制器中的另一个 UIBarButtonItem 替换后退按钮?

php require_once 文件路径中的变量

如何用sed中的另一个路径替换路径?

用文件中的另一个词替换特定词[关闭]

如何替换文件中的特定字符