1

Possible Duplicate:
How can I replace lines in a text file with lines from another file based on matching key fields?

I want to merge the following files and I want the contents of FileB.txt to overwrite FileA.txt where there are common lines, but I don't want to completely replace FileA.txt with FileB.txt.

For example:

File 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

File 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 =

In this case The merge result should be:

# 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 =

So anything before the '=' on each line should be checked and matched between FileA.txt and FileB.txt. If any after the '=' on FileB.txt differs from FileA.txt then whatever is in FileB.txt should be written to FileA.txt.

4

4 回答 4

2

试试这个sort命令:

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

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

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

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

-s: 稳定排序。如果两行基于它们的排序字段相同,则在输入中首先看到的行在输出中仍然是最先出现的。

通过FileB.txt首先放入输入文件列表,您可以确保 如果它们共享相同的密钥,FileB.txt则选择line from 而不是 line from。FileA.txt

于 2012-06-01T13:34:05.993 回答
1

这是纯粹的 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
于 2012-06-01T07:22:03.417 回答
1
#!/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
于 2012-06-01T11:36:07.493 回答
0
{
    # 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
于 2012-06-01T10:32:18.023 回答