按块名称合并两个 ini 文件
merge two ini files by their block name
如何合并两个 ini 文件的两个块?
您好,我有两个 ini 文件,它们以块的形式存储数据,如下所示:
-->cat f1
[default]
a1=1
b1=2
c1=3
[foo]
d=1
e1=5
-->cat f2
[default]
a2=5
b2=6
[foo]
c2=7
d2=8
e2=9
[bar]
f2=10
我需要按如下方式合并这两个文件:
[default]
a1=1
b1=2
c1=3
a2=5
b2=6
[foo]
d=1
e1=5
c2=7
d2=8
e2=9
[bar]
f2=10
老实说,我不知道从哪里开始,需要什么逻辑或工具。
我试图获取方向的一些愚蠢的事情是:
awk 'NR==FNR{a[[=12=]]=[=12=];next} [=12=] in a{print}' f1 f2
[default]
[foo]
awk -vRS='' '{=}1' f1 f2 |awk '!a[]++'
[default] a1=1 b1=2 c1=3
[foo] d=1 e1=5
[bar] f2=10
Perl 解决方案是使用像 Config::Tiny to read each, merge the resulting data structure, and write out a new file. Note this does not preserve comments or ordering (for the latter, you could use Config::Tiny::Ordered 这样的 INI 解析器,但合并更难)。
use strict;
use warnings;
use Config::Tiny;
my $config1 = Config::Tiny->read('f1');
my $config2 = Config::Tiny->read('f2');
foreach my $category (keys %$config2) {
my $section1 = $config1->{$category} //= {};
my $section2 = $config2->{$category};
@$section1{keys %$section2} = values %$section2;
}
$config1->write('new');
使用 awk
你可以这样做:
awk '/^$/{
next
}
/^\[.*\]$/{
hdr = [=10=]
next
}
a[hdr] != "" {
a[hdr] = a[hdr] ORS [=10=]
next
}
{
a[hdr] = [=10=]
seq[++n] = hdr
}
END {
for (i=1; i<=n; i++)
print seq[i] ORS a[seq[i]] (i<n ? ORS : "")
}' f1 f2
[default]
a1=1
b1=2
c1=3
a2=5
b2=6
[foo]
d=1
e1=5
c2=7
d2=8
e2=9
[bar]
f2=10
详情:
/^$/
匹配我们忽略的所有空行
/^\[.*\]$/
匹配 header 我们存储在 hdr
变量中的名字
a[hdr] != "" { ... }
当我们已经处理了 hdr
一次时,我们在索引为 hdr
的数组 a
中追加一个新行和当前行
- 否则我们只是将当前行存储在由
hdr
索引的数组 a
中。此外,我们将 hdr
存储在另一个数组 seq
中,该数组按递增数字索引以按顺序打印数据
- 在
END
块中,我们遍历 seq
数组并打印每个 header 和详细信息块。如果我们有更多数据要处理,我们会附加一个换行符。
$ cat tst.awk
BEGIN { RS=""; ORS="\n\n"; FS=OFS="\n" }
{ key = }
NR == FNR { rec[key] = [=10=]; next }
key in rec { = rec[key]; delete rec[key] }
{ print }
END {
for (key in rec) {
print rec[key]
}
}
$ awk -f tst.awk file1 file2
[default]
a1=1
b1=2
c1=3
a2=5
b2=6
[foo]
d=1
e1=5
c2=7
d2=8
e2=9
[bar]
f2=10
这可能对你有用(GNU diff & sed):
diff -au999 file1 file2 | sed '1,3d;s/.//' >file3
使用diff -u999
统一file1和fil2,然后删除3header行和每行的第一个字符。
N.B。如果 file1 和 file2 相同,您将不会得到任何输出,并且如果它们具有不同的值,则会重复相同的键。
如何合并两个 ini 文件的两个块?
您好,我有两个 ini 文件,它们以块的形式存储数据,如下所示:
-->cat f1
[default]
a1=1
b1=2
c1=3
[foo]
d=1
e1=5
-->cat f2
[default]
a2=5
b2=6
[foo]
c2=7
d2=8
e2=9
[bar]
f2=10
我需要按如下方式合并这两个文件:
[default]
a1=1
b1=2
c1=3
a2=5
b2=6
[foo]
d=1
e1=5
c2=7
d2=8
e2=9
[bar]
f2=10
老实说,我不知道从哪里开始,需要什么逻辑或工具。
我试图获取方向的一些愚蠢的事情是:
awk 'NR==FNR{a[[=12=]]=[=12=];next} [=12=] in a{print}' f1 f2
[default]
[foo]
awk -vRS='' '{=}1' f1 f2 |awk '!a[]++'
[default] a1=1 b1=2 c1=3
[foo] d=1 e1=5
[bar] f2=10
Perl 解决方案是使用像 Config::Tiny to read each, merge the resulting data structure, and write out a new file. Note this does not preserve comments or ordering (for the latter, you could use Config::Tiny::Ordered 这样的 INI 解析器,但合并更难)。
use strict;
use warnings;
use Config::Tiny;
my $config1 = Config::Tiny->read('f1');
my $config2 = Config::Tiny->read('f2');
foreach my $category (keys %$config2) {
my $section1 = $config1->{$category} //= {};
my $section2 = $config2->{$category};
@$section1{keys %$section2} = values %$section2;
}
$config1->write('new');
使用 awk
你可以这样做:
awk '/^$/{
next
}
/^\[.*\]$/{
hdr = [=10=]
next
}
a[hdr] != "" {
a[hdr] = a[hdr] ORS [=10=]
next
}
{
a[hdr] = [=10=]
seq[++n] = hdr
}
END {
for (i=1; i<=n; i++)
print seq[i] ORS a[seq[i]] (i<n ? ORS : "")
}' f1 f2
[default]
a1=1
b1=2
c1=3
a2=5
b2=6
[foo]
d=1
e1=5
c2=7
d2=8
e2=9
[bar]
f2=10
详情:
/^$/
匹配我们忽略的所有空行/^\[.*\]$/
匹配 header 我们存储在hdr
变量中的名字a[hdr] != "" { ... }
当我们已经处理了hdr
一次时,我们在索引为hdr
的数组 - 否则我们只是将当前行存储在由
hdr
索引的数组a
中。此外,我们将hdr
存储在另一个数组seq
中,该数组按递增数字索引以按顺序打印数据 - 在
END
块中,我们遍历seq
数组并打印每个 header 和详细信息块。如果我们有更多数据要处理,我们会附加一个换行符。
a
中追加一个新行和当前行
$ cat tst.awk
BEGIN { RS=""; ORS="\n\n"; FS=OFS="\n" }
{ key = }
NR == FNR { rec[key] = [=10=]; next }
key in rec { = rec[key]; delete rec[key] }
{ print }
END {
for (key in rec) {
print rec[key]
}
}
$ awk -f tst.awk file1 file2
[default]
a1=1
b1=2
c1=3
a2=5
b2=6
[foo]
d=1
e1=5
c2=7
d2=8
e2=9
[bar]
f2=10
这可能对你有用(GNU diff & sed):
diff -au999 file1 file2 | sed '1,3d;s/.//' >file3
使用diff -u999
统一file1和fil2,然后删除3header行和每行的第一个字符。
N.B。如果 file1 和 file2 相同,您将不会得到任何输出,并且如果它们具有不同的值,则会重复相同的键。