【问题标题】:Change an exact word on exact roll in ASCII file更改 ASCII 文件中精确滚动的精确单词
【发布时间】:2017-01-10 19:20:12
【问题描述】:

我需要更改文件中的字符串,该字符串在每一行都重复,但我只需要更改几行(而不是所有行)。 比方说,/etc/fstab 文件:

/dev/mapper/rhel-root            /                       xfs     defaults        0 0
/dev/mapper/rhel-boot            /boot                   ext4    defaults        1 2
/dev/mapper/rhel-home            /home                   ext3    defaults        1 2
/dev/mapper/rhel-var             /var                    ext3    defaults        1 2
/dev/mapper/workvg-swaplv        swap                    swap    defaults        0 0

如何将“defaults”字符串更改为仅适用于 /home 和 /var 条目的“string”? 我尝试过的想法是使用了很多 grep|sed|exargs 等的组合,但它没有按预期工作:)

echo $(egrep "/var | /home" fstab | awk '{ print $4}') | xargs -I '{}' sed 's/{}/string/' fstab

有人可以给我一些想法吗? 提前谢谢你们!

【问题讨论】:

    标签: sed grep xargs


    【解决方案1】:
    $ sed -E '/\/(home|var)/ s/defaults/string/' fstab
    /dev/mapper/rhel-root            /                       xfs     defaults        0 0
    /dev/mapper/rhel-boot            /boot                   ext4    defaults        1 2
    /dev/mapper/rhel-home            /home                   ext3    string        1 2
    /dev/mapper/rhel-var             /var                    ext3    string        1 2
    /dev/mapper/workvg-swaplv        swap                    swap    defaults        0 0
    
    • -E 使用扩展正则表达式
    • /\/(home|var)/ 仅匹配带有/home/var 的行
    • s/defaults/string/ 用替换字符串替换所需的模式

    编辑:

    为了更稳健的匹配:

    sed -E '/^\S+\s+\/(home|var)\b/ s/^((\S+\s+){3})defaults\b/\1string/' fstab
    

    这会检查第 2 列中 /home/var 的完全匹配,并替换第 4 列中 defaults 的完全匹配

    \b 检查单词边界,\s 匹配空格,\S 匹配非空格

    【讨论】:

    • 虽然这将在给定发布的示例输入的情况下产生预期的输出,但有很多方法会因其他输入而失败,例如如果 rhel-boot 是 home-boot 或者如果字符串包含 & 或者如果 mapper 是默认值或 .... 所以 - 使用它时要小心!
    【解决方案2】:
    $ awk '/\/var/ || /\/home {sub(/defaults/, "string")} 1'` /etc/fstab
    
    • /\/var || /\/home如果记录中有关键字
    • sub{/defaults/, "string") 将第一个“默认值”替换为“字符串”
    • 1打印更改和未更改的记录

    【讨论】:

      【解决方案3】:

      这对于所有输入行以及所有不包含反斜杠的 defaultsstring 值都非常有效(如果您有反斜杠,则可以轻松调整):

      $ cat tst.awk
      BEGIN { split(entries,t); for (i in t) tgts["/"t[i]] }
      ($2 in tgts) && match($0,/^((\S+\s+){3})(\S+)(\s.*)$/,a) && (a[3]==old) { $0 = a[1] new a[4] }
      { print }
      
      $ awk -v entries="home var" -v old="defaults" -v new="string" -f tst.awk file
      /dev/mapper/rhel-root            /                       xfs     defaults        0 0
      /dev/mapper/rhel-boot            /boot                   ext4    defaults        1 2
      /dev/mapper/rhel-home            /home                   ext3    string        1 2
      /dev/mapper/rhel-var             /var                    ext3    string        1 2
      /dev/mapper/workvg-swaplv        swap                    swap    defaults        0 0
      

      它使用 GNU awk 作为第三个参数来 match(),其他 awk 将使用 substr()。

      【讨论】:

        【解决方案4】:
        awk '/home|var/{sub(/defaults/,"string  ")}1' file
        
        /dev/mapper/rhel-root            /                       xfs     defaults        0 0
        /dev/mapper/rhel-boot            /boot                   ext4    defaults        1 2
        /dev/mapper/rhel-home            /home                   ext3    string          1 2
        /dev/mapper/rhel-var             /var                    ext3    string          1 2
        /dev/mapper/workvg-swaplv        swap                    swap    defaults        0 0
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-16
          • 2018-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-10-21
          • 2011-02-07
          相关资源
          最近更新 更多