【问题标题】:Find unique string within a file, up a line and append?在文件中查找唯一字符串,向上一行并追加?
【发布时间】:2012-12-07 04:33:33
【问题描述】:

有人可以帮我解决这个问题吗?我正在寻找可用于在配置文件 (Linux) 中查找唯一字符串的 SED 或 AWK 命令,向上一行并将字符串附加到该行的末尾?

例如:

配置文件:

定义主机组{
主机组名称 http-urls ;主机组名称
别名 HTTP URL;组的长名称
成员 domain1.com, domain2.com, domain3.com,
#MyUniqueString
}

在上面的例子中,我想使用 SED 或 AWK 来查找 #MyUniqeString,向上一行以 members 开头并附加 " domain4.com" 在行尾。

我在下面找到了这个问题,但我需要先在文本文件中搜索字符串,然后再往上走一行。

Bash script: Appending text at the last character of specific line of a file

有什么建议吗?

【问题讨论】:

    标签: linux bash sed awk


    【解决方案1】:

    三种不同解决方案的比较

    较小,使用sed:

    sed -e ':a;N;/\n#MyUniqueString/{s/\n/ domain4.com\n/};H;s/\n.*$//;p;g;s/^.*\n//;ta;' config.file
    

    这可以运行为:

    sed -e '
       :a;
        N;
        /\n#MyUniqueString/{
            s/\n/ domain4.com\n/
        };
        H;
        s/\n.*$//;
        p;
        g;
        s/^.*\n//;
        ta;
       ' config.file
    

    分析:

    time sed ':a;N;/\n#MyUniqueString/{s/\n/ domain4.com\n/};H;
                          s/\n.*$//;p;g;s/^.*\n//;ta;' config.file 
    define hostgroup{
    hostgroup_name http-urls ; The name of the hostgroup
    alias HTTP URLs ; Long name of the group
    members domain1.com, domain2.com, domain3.com, domain4.com
    #MyUniqueString
    }
    
    
    
    real    0m0.010s
    user    0m0.000s
    sys     0m0.008s
    

    为什么不纯 bash

    由于没有分叉,这可能非常快(如果来自bash 并且不会太长配置文件):

    readarray configFile < ./config.file
    for ((i=${#configFile};i--;));do
        [[ "${configFile[i]}" =~ "#MyUniqueString" ]] && break
      done
    configFile[i-1]+=" domain4.com"
    printf "%s\n" "${configFile[@]//$'\n'/}"
    

    分析运行者:

    time {
        readarray configFile < ./config.file
        for ((i=${#configFile};i--;));do
            [[ "${configFile[i]}" =~ "#MyUniqueString" ]] && break
          done
        configFile[i-1]+=" domain4.com"
        printf "%s\n" "${configFile[@]//$'\n'/}"
    }
    

    将给予:

    define hostgroup{
    hostgroup_name http-urls ; The name of the hostgroup
    alias HTTP URLs ; Long name of the group
    members domain1.com, domain2.com, domain3.com, domain4.com
    #MyUniqueString
    }
    
    real    0m0.001s
    user    0m0.000s
    sys     0m0.000s
    

    awk测试

    time awk '{a[NR]=$0}/#MyUniqueString/{a[NR-1]=a[NR-1]" domain4.com"}END{for(i=1;i<=NR;i++)print a[i]}' config.file 
    define hostgroup{
    hostgroup_name http-urls ; The name of the hostgroup
    alias HTTP URLs ; Long name of the group
    members domain1.com, domain2.com, domain3.com, domain4.com
    #MyUniqueString
    }
    
    real    0m0.009s
    user    0m0.004s
    sys     0m0.000s
    

    【讨论】:

    • 你的环境是什么? (我在 Debian GNU/Linux 6.0.5 上运行 GNU sed 版本 4.2.1
    【解决方案2】:

    这个 awk 解决方案只需要记住上一行

    awk '
        /#MyUniqueString/ {prev = prev "domain4.com"} 
        NR > 1 {print prev}
        {prev=$0}
        END {print prev}
    '
    

    【讨论】:

      【解决方案3】:

      这是另一个使用反向引用的 sed 解决方案:

      sed '{N; N; s/\(.*\)\n\(#MyUniqueString\)/\1domain4.com\n\2/g}' config.file
      

      【讨论】:

      • 这很奇怪......它适用于您的示例数据。哦,好吧,只要你以某种方式得到你想要的结果。
      【解决方案4】:

      您可以使用ed 有效地做到这一点:

      ed yourfile <<-'EOF'
          /#MyUniqueString/ # Find the matching line
          - # Go up a line
          a # Append text
          domain4.com
          . # Stop appending
          .-1,.j # Join the line above with the appended line
          w # Write the line
      EOF
      

      【讨论】:

      • 哦,它有效。 cmets 是为了您的利益,而不是为了粘贴。
      【解决方案5】:

      试试这个单线:

      awk '{a[NR]=$0}/#MyUniqueString/{a[NR-1]=a[NR-1]"domain4.com"}END{for(i=1;i<=NR;i++)print a[i]}' configFile
      

      测试

      kent$  cat test.txt 
      define hostgroup{
      hostgroup_name http-urls ; The name of the hostgroup
      alias HTTP URLs ; Long name of the group
      members domain1.com, domain2.com, domain3.com,
      #MyUniqueString
      }
      
      kent$  awk '{a[NR]=$0}/#MyUniqueString/{a[NR-1]=a[NR-1]"domain4.com"}END{for(i=1;i<=NR;i++)print a[i]}' test.txt 
      define hostgroup{
      hostgroup_name http-urls ; The name of the hostgroup
      alias HTTP URLs ; Long name of the group
      members domain1.com, domain2.com, domain3.com,domain4.com
      #MyUniqueString
      }
      

      【讨论】:

      • 谢谢你 - 我尝试了一些其他的,这个最适合你的问题并且可以按照你的说明工作。
      猜你喜欢
      • 1970-01-01
      • 2023-03-27
      • 2017-07-26
      • 1970-01-01
      • 1970-01-01
      • 2014-06-27
      • 2013-02-22
      • 2013-05-02
      • 2019-11-08
      相关资源
      最近更新 更多