【问题标题】:How do I merge FileA.txt and FileB.txt giving FileB.txt overwrite power using a bash script? [duplicate]如何使用 bash 脚本合并 FileA.txt 和 FileB.txt,赋予 FileB.txt 覆盖能力? [复制]
【发布时间】:2012-06-01 06:45:01
【问题描述】:

可能重复:
How can I replace lines in a text file with lines from another file based on matching key fields?

我想合并以下文件,我希望 FileB.txt 的内容覆盖有共同行的 FileA.txt,但我不想用 FileB.txt 完全替换 FileA.txt。

例如:

文件 A:

# cat FileA.txt 
interface.1.type = ethernet
interface.1 = A
interface.1.ip = 192.168.1.1
interface.1.netmask = 255.255.255.0
interface.1.dhcp = false

文件 B:

# cat FileB.txt 
interface.1 = B
interface.1.ip = 192.168.1.1
interface.1.netmask = 
interface.1.dhcp = true
interface.1.dhcp.range = 192.168.1.1,192.168.1.15
interface.1.extraline =

在这种情况下 合并结果应该是:

# cat FileA.txt
interface.1.type = ethernet
interface.1 = B
interface.1.ip = 192.168.1.1
interface.1.netmask = 
interface.1.dhcp = true
interface.1.dhcp.range = 192.168.1.1,192.168.1.15
interface.1.extraline =

因此,应检查每行“=”之前的任何内容,并在 FileA.txt 和 FileB.txt 之间进行匹配。如果 FileB.txt 上的 '=' 之后的任何内容与 FileA.txt 不同,则 FileB.txt 中的任何内容都应写入 FileA.txt。

【问题讨论】:

  • 这不是我想用 bash 写的东西...

标签: bash properties merge match


【解决方案1】:

试试这个sort 命令:

sort -t= -k1,1 -us FileB.txt FileA.txt

-t=:将行拆分为 '=' 上的字段,因此您正在对键进行排序

-k1,1:按第一个字段排序。这很重要,因为重复(见下文)取决于 仅在指定的排序字段上。

-u:消除重复。如果两行有相同的键,则只保留第一行。

-s: 稳定排序。如果两行基于其排序字段相同,则 在输入中首先出现在输出中仍然是第一个。

通过首先将FileB.txt 放在输入文件列表中,您可以确保从 如果FileB.txt 共享相同的密钥,则从FileA.txt 中选择FileB.txt

【讨论】:

  • 这个命令绝对是最短最容易理解的。
【解决方案2】:

这是纯粹的 BASH 方式,一致性和性能被抛到脑后。这是您永远不会在关键应用程序中使用的东西。

如果您在关键应用程序中使用它,请考虑寻找配置库。例如,在 Java 中,Properties 类对此非常有用。这适用于简单的脚本,但您可能需要稍微更改正则表达式。

如果正确转义或引用,属性文件在一行中包含多个“=”并不违法。在这个脚本中它可能会导致问题

#!/bin/bash
FILEA="filea.txt"
FILEB="fileb.txt"
RESULT="filec.txt"
:> $RESULT

while read line; do
    ELEM=$(echo $line | perl -pe 's/\s*\=.*?$//gi')
    FILEBLINE=$(grep "^\s*$ELEM" $FILEB)
    if [[ -n $FILEBLINE ]]; then
        echo $FILEBLINE >>$RESULT
    else
        echo $line >>$RESULT
    fi
done < $FILEA

【讨论】:

    【解决方案3】:
    #!/usr/bin/awk -f
    BEGIN {
        FS = " = ?"; OFS = " = "
    }
    
    NR == FNR {
        attrib[$1] = $2
        printed[$1] = 0
        next
    }
    
    (! ($1 in attrib)) {
        print
    }
    
    $1 in attrib && $2 != attrib[$1] {
        print $1, attrib[$1]
        printed[$1] = 1
    }
    
    END {
        for (i in printed) {
            if (! printed[i]) {
                print i, attrib[i]
            }
        }
    }
    

    像这样运行它:

    $ ./interfacemerge FileB.txt FileA.txt
    

    【讨论】:

      【解决方案4】:
      {
          # print the fileA settings not in fileB
          awk -F= 'NR==FNR {lhs[$1]; next} !($1 in lhs)' fileB.txt fileA.txt
      
          # then print all of fileB
          cat fileB.txt
      
          # then write to a new file and overwrite fileA
      } > newfile && mv newfile fileA.txt
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-13
        • 2016-11-17
        • 2017-07-30
        • 1970-01-01
        • 2018-02-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多