Bash - 如何更新引号内的内容,但前提是它是数字?

Bash - 如何更新引号内的内容,但前提是它是数字?

对于这个项目,我们有数百个使用composer.json 的应用程序。我正在使用 Bash 脚本来检查和更新包含正在获取新版本的应用程序的任何文件的版本号。

例如,原始文件如下所示(我只放入相关部分):

{
"name" : "test/graylogger"
"version" : "1.1.1"
...
"require": {
    "test/phpunit": "4.8.23"
}

我想将其更新为:

{
"name" : "test/graylogger"
"version" : "1.1.2"
...
"require": {
    "test/phpunit": "4.8.24"
}

但是,它最终是这样的(我不想要):

{
"name" : "1.1.2"
"version" : "1.1.2"
...
"require": {
    "test/phpunit": "4.8.24"
}

基本上,我的脚本应该搜索“版本”,将其后的第二个引号更新一,然后根据文件夹文件名(在本例中为“graylogger”)循环,然后在任何包含该应用程序的其他文件夹。但由于某种原因,它也更新了名称,这是我不想要的。这是我执行此操作的代码片段:

while read line2; do

   line1="$line1\"" #I did this to prevent any repetitive names from upping twice
   original=$(grep -hr "$line1" /Websites/"$line2"/composer.json | awk -F \" '{print $4}')

   if [["$original" != *"$line1"*]]; then
      sed -i'' s,"$original","$version",g composer.json

done < websites.txt

line1是文件中正在更新的应用程序。

line2是正在更新的文件。

我尝试制作一个 if 语句,如果第二个文本中的文本包含应用程序的名称,则排除更改,它不会更新,但它似乎不起作用。

这是在 Mac 上完成的。

谢谢!

答案1

jq是一个在命令行处理JSON的工具,并且比基本的文本修改更适合处理这样的结构化数据。这是一些似乎与您实际想做的事情相匹配的 jq:

program=test/graylogger
version=1.1.2
jq --arg prog "$program" --arg version "$version" '
    (.. | select(.name? == $prog).version) = $version
    |   (.. | select(has($prog)?)[$prog]) = $version' composer.json | sponge composer.json

jq 程序本身就是单引号中的两行。

它将取代两个都任何“名称”为 test/graylogger 的对象的“版本”属性(第二行开头的jq程序) and thetest/graylogger property of any object that has one (the second line of thejq |` 的第一行是将它们分开,所以如果您只有一个,则可以program) with the new version. You can edit to only one or the other as appropriate - the pipe把它拿出来。

第一行的工作原理是使用以下命令查找任何合适的对象..|select(.name? == $prog):look at每一个value ( ..) 并继续仅查看那些name我们正在寻找的对象(并且根本有 a name),然后通过在该对象上设置版本属性 ( .version = $version)。

第二行类似地挑选出has键与程序名称匹配的任何对象,然后使用[]索引更新该属性。

我用过sponge来自 moreutils复制sed -i就地覆盖文件的行为。您可以改用临时文件。所有这些都可以进入任何要应用于所有文件的现有循环结构。

相关内容