【问题标题】:Trying to use sed to edit a configuration file from a bash script to edit a key/value pair尝试使用 sed 从 bash 脚本编辑配置文件以编辑键/值对
【发布时间】:2020-12-22 08:43:26
【问题描述】:

我有一个配置文件,其中包含我需要从 bash 脚本修改的每行 1 个键/值对。这有点棘手,因为我需要修改一个特定的键/值对,它可能不存在于文件中,它可能存在但为空,或者它可能存在但已填充,如下所述。

文件的示例片段:

additional.urls=
cache.enable=true
compiler.cache_core=true

我需要找到键/值对“additional.urls=”并修改它。但没有什么是容易的,首先可能会填充该行,或者它可能根本不存在于文件中。

additional.urls=

additional.urls=https://myurl.me

如果键/值对为空(= 之后除了空格之外什么都没有),那么我想将 url 附加到行尾:https://newurl.it:

additional.urls=https://newurl.it

如果全部丢失,我想将整个键/值行插入到文件中,最好是在顶部,但这并不重要。

然后它会变得更棘手,如果它已经有一个值(可能是 1 个或多个 url 逗号分隔)我需要保留已经存在的所有内容并附加到行尾添加一个逗号,然后是新的 url:

additional.urls=https://myurl1.me,https://myurl2.me
变为:
additional.urls=https://myurl1.me,https://myurl2.me,https://newurl.it

我不知道该怎么做。如果只是搜索和替换,我知道该怎么做,但条件让我发疯。也许 sed 不是正确的答案,是 awk 更好还是别的什么?我只是不知道。

【问题讨论】:

    标签: regex bash awk sed grep


    【解决方案1】:

    这可能对你有用(GNU sed):

    sed -zEi ':a;
              s#^additional\.urls=.*#&,https://newurl.it#m;
              s/^(additional\.urls=),/\1/m;
              t;
              s/^/additional.urls=\n/;
              ta' file
    

    将文件拖入内存 (-z),使用扩展正则表达式 (-E) 并就地编辑 (-i)。

    ,https://newurl.it 附加到以additional.urls= 开头的行。

    如果存在以additional.urls=, 开头的行,则删除,

    如果任一替换成功,则退出。

    否则,在文件开头插入additional.urls=\n,然后重复。

    注意使用m 标志替换多行处理。

    命令可能会被展平:

    sed -zEi ':a;s#^additional\.urls=.*#&,https://newurl.it#m;s/^(additional\.urls=),/\1/m;t;s/^/additional.urls=\n/;ta' file
    

    【讨论】:

    • 由于某种原因,这总是在文件顶部插入一个新行。如果你运行它两次,你会在文件的顶部看到两行。我正在尝试所有建议,然后尽我所能进行调试。谢谢。
    【解决方案2】:

    您可以使用此awk 解决方案来满足所有 3 个条件:

    awk -i inplace -v key='additional.urls' -v val='https://newurl.it' '
    BEGIN {
       FS=OFS="="
    }
    $1 == key {
       $2 = ($2 ~ /^[[:blank:]]*$/ ? "" : $2 ",") val
       p = 1
    }
    END {
       if (!p)
          print key, val
    } 1' file
    
    additional.urls=https://newurl.it
    cache.enable=true
    compiler.cache_core=true
    

    【讨论】:

      【解决方案3】:
      awk -F= -v add="additional.urls=test" '
          { a[$1]=$2 }
          END{ 
             split(add,b,"="); 
             a[b[1]]=(a[b[1]]~/^[[:blank:]]*/ ? "" : a[b[1]]",") b[2]; 
             OFS="="; 
             for(i in a){ print i,a[i] }}' configuration-file
      

      .

      cache.enable=true
      additional.urls=test
      compiler.cache_core=true
      

      【讨论】:

        【解决方案4】:

        sed 通过 e 切换到 sed 中的代码 sh 提供。请参阅下面的示例并根据您的需要进行修改。

        首先,匹配的单词将分配给变量ab。随后,它们可以在ifswitch 语句中使用。

        echo -e "foo=\nbar=rab\nzar=raz" | sed -E 's/(.+)=(.*)/ a=\1; b=\2; if [[ $b ]]; then echo "$a=$b"; else case "$a" in foo) echo "$a=oof";; *) echo "$a=$(rev <<< $b)";; esac; fi/e'
        

        【讨论】:

          【解决方案5】:

          为了保持整个内容的可读性,不要试图在一个语句中做太多:

          if ! grep -q "additional.urls=" file
          then
              # If line does not exist, add it at top.
              sed -i '1s/^/additional.urls=http:\/\/newurl.it\n/' file
          else
              #         If value is non-empty, add comma    Append newurl.it to end of the list
              sed -i -e "s/\(additional.urls=.\+\)/\1,/" -e "s/\(additional.urls=.*\)/\1http:\/\/newurl.it/" file
          fi
          

          【讨论】:

            猜你喜欢
            • 2022-07-12
            • 2011-05-26
            • 1970-01-01
            • 2017-05-04
            • 2018-01-15
            • 2022-12-15
            • 2014-08-29
            • 2021-03-23
            • 1970-01-01
            相关资源
            最近更新 更多