我想用该文件中的另一个路径替换 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 文件中的路径的主要内容,如果未能解决你的问题,请参考以下文章