Awk 按块名合并两个ini文件

Awk 按块名合并两个ini文件,awk,ini,Awk,Ini,如何合并两个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=

如何合并两个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[$0]=$0;next} $0 in a{print}' f1 f2
[default]

[foo]

awk -vRS='' '{$1=$1}1' f1 f2 |awk '!a[$1]++'
[default] a1=1 b1=2 c1=3
[foo] d=1 e1=5
[bar] f2=10

Perl解决方案是使用一个INI解析器来读取每个数据,合并生成的数据结构,并写出一个新文件。注意,这不会保留注释或顺序(对于后者,您可以使用,但合并更难)


Perl解决方案是使用一个INI解析器来读取每个数据,合并生成的数据结构,并写出一个新文件。注意,这不会保留注释或顺序(对于后者,您可以使用,但合并更难)


使用
awk
可以执行以下操作:

awk '/^$/{
   next
}
/^\[.*\]$/{
   hdr = $0
   next
}
a[hdr] != "" {
   a[hdr] = a[hdr] ORS $0
   next
}
{
   a[hdr] = $0
   seq[++n] = hdr
}
END {
   for (i=1; i<=n; i++)
      print seq[i] ORS a[seq[i]] (i<n ? ORS : "")
}' f1 f2
详细信息:

  • /^$/
    匹配我们忽略的所有空行
  • /^\[.\]$/
    匹配了我们存储在
    hdr
    变量中的标题名称
  • a[hdr]!=“{…}
    当我们已经处理了
    hdr
    一次之后,我们在数组
    a
    中追加一个新行和当前行,该数组由
    hdr
    索引
  • 否则,我们只将当前行存储在数组
    a
    中,该数组由
    hdr
    索引。此外,我们还将
    hdr
    存储在另一个数组
    seq
    中,该数组通过递增数字进行索引,以便按顺序打印数据
  • END
    块中,我们循环通过
    seq
    数组并打印每个标题和详细信息块。如果我们有更多的数据要处理,我们会添加一个换行符

使用
awk
可以执行以下操作:

awk '/^$/{
   next
}
/^\[.*\]$/{
   hdr = $0
   next
}
a[hdr] != "" {
   a[hdr] = a[hdr] ORS $0
   next
}
{
   a[hdr] = $0
   seq[++n] = hdr
}
END {
   for (i=1; i<=n; i++)
      print seq[i] ORS a[seq[i]] (i<n ? ORS : "")
}' f1 f2
详细信息:

  • /^$/
    匹配我们忽略的所有空行
  • /^\[.\]$/
    匹配了我们存储在
    hdr
    变量中的标题名称
  • a[hdr]!=“{…}
    当我们已经处理了
    hdr
    一次之后,我们在数组
    a
    中追加一个新行和当前行,该数组由
    hdr
    索引
  • 否则,我们只将当前行存储在数组
    a
    中,该数组由
    hdr
    索引。此外,我们还将
    hdr
    存储在另一个数组
    seq
    中,该数组通过递增数字进行索引,以便按顺序打印数据
  • END
    块中,我们循环通过
    seq
    数组并打印每个标题和详细信息块。如果我们有更多的数据要处理,我们会添加一个换行符
这可能适用于您(GNU diff&sed):

使用
diff-u999
统一文件1和文件2,然后删除3个标题行和每行的第一个字符

注意:如果文件1和文件2相同,您将不会得到任何输出,如果它们的值不同,相同的键将重复。

这可能适用于您(GNU diff&sed):

使用
diff-u999
统一文件1和文件2,然后删除3个标题行和每行的第一个字符



注意:如果文件1和文件2是相同的,您将不会得到任何输出,如果它们具有不同的值,则相同的键将重复。

如果文件包含相同的键但具有不同的值,该怎么办?注释行(如果有的话)的情况如何。
f2
应该覆盖
f1
的键(如果是DUP)。重复评论没问题,我可以接受。你不会说有一天评论会在你睡觉的时候刺伤你。但是我的要求看起来很有挑战性,至少现在不能考虑评论。如果文件包含相同的键但值不同怎么办?注释行(如果有的话)的情况如何。
f2
应该覆盖
f1
的键(如果是DUP)。重复评论是可以的,我可以接受。你不会说有一天评论会在你睡觉的时候刺伤你。但是我的要求看起来很有挑战性,至少现在我想不出评论了。谢谢,你能不能高层次地解释一下,这样我就可以继续了,我将在回答中添加更多细节。
ord
是某些awk和
ordchr
gawk扩展中的函数名。为数组使用不同的名称以便于移植。啊,谢谢Ed。我不知道
ord
是函数。是的,
ord()
返回字符的序号。请看。谢谢,你能不能给我一个高层次的解释,这样我就可以继续了,我将在回答中添加更多的细节。
ord
是一些awk和
ordchr
gawk扩展中的函数名。为数组使用不同的名称以便于移植。啊,谢谢Ed。我不知道
ord
是函数。是的,
ord()
返回字符的序号。请参阅。感谢您的帮助,尽管我没有在系统中安装此模块。感谢您的helpConfig::Tiny是纯perl,因此可以将其放入脚本中。您当然需要安装App::FatPacker来完成此操作,但基本过程是:安装App::cpanminus或从下载它
cpanm-l本地配置::Tiny
<代码>fatpack树$(env PERL5LIB=“$PWD/local/lib/perl5”用于Config/Tiny.pm的fatpack包列表)
fatpack文件script.pl>script.packed.pl
感谢您的帮助,尽管我没有在系统中安装此模块。感谢您的helpConfig::Tiny是纯perl,因此可以将其放入脚本中。您当然需要安装App::FatPacker来完成此操作,但基本过程是:安装App::cpanminus或从下载它
cpanm-l本地配置::Tiny
<代码>fatpack树$(env PERL5LIB=“$PWD/local/lib/perl5”用于Config/Tiny.pm的fatpack包列表)
fatpack文件script.pl>script.packed.pl
这可能只在非常简单的情况下有效;例如,如果节的顺序不同,它将失败。这可能只适用于非常简单的情况;例如,如果节的顺序不同,它将失败。
[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
$ cat tst.awk
BEGIN { RS=""; ORS="\n\n"; FS=OFS="\n" }
{ key = $1 }
NR == FNR { rec[key] = $0; next }
key in rec { $1 = 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
diff -au999 file1 file2 | sed '1,3d;s/.//' >file3