问题
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.
回答1:
Try this sort
command:
sort -t= -k1,1 -us FileB.txt FileA.txt
-t=
: split the lines into fields on the '=', so you are sorting on the keys
-k1,1
: sort on the first field. This is important, as duplication (see below) depends
only on the specified sort field.
-u
: eliminate duplicates. If two lines have the same key, only the first is kept.
-s
: stable sort. If two lines are identical based on their sort field, the line that
is seen first in the input remains first in the output.
By putting FileB.txt
in the list of input files first, you ensure that the line from
FileB.txt
is chosen over the line from FileA.txt
if they share the same key.
回答2:
Here's the pure BASH way, consistency and performance are thrown overboard. This is something you would never use in a critical application.
If you are using this in a critical application, consider looking for a configuration library. In Java for instance, the Properties class is great for this. This works for simple scripts though, you might have to change the regular expression a bit.
It's not illegal for property files to contain more than one "=" on one line if properly escaped or quoted. In this script it might cause problems
#!/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]
}
}
}
Run it like this:
$ ./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
来源:https://stackoverflow.com/questions/10845601/how-do-i-merge-filea-txt-and-fileb-txt-giving-fileb-txt-overwrite-power-using-a