编写 bash 代码循环逐行读取具有值的文件,第一个单词作为一行并创建 csv

编写 bash 代码循环逐行读取具有值的文件,第一个单词作为一行并创建 csv

我有这个样本数据

dn; uid=456456456,cn=users,dc=efsfb,dc=org,dc=co;
objectclass; top;
objectclass; person;
objectclass; organizationalPerson;
objectclass; inetOrgPerson;
uid; 456456456;
givenName; MONICA;
employeeType; CC;
telephoneNumber;456456456;
telexNumber;958;
postalAddress;19770726;
initials; ARBOLEDA;
title; F;
cn; MONICA ARBOLEDA RAIGOSA;
mail; [email protected];
sn; RAIGOSA;
userPassword;;
ibm-entryuuid;;
;;
dn; uid=456456,cn=users,dc=efsfb,dc=org,dc=co;
objectclass; top;
objectclass; person;
objectclass; organizationalPerson;
objectclass; inetOrgPerson;
uid; 456456456;
givenName; SONIA ESPERANZA;
employeeType; CC;
telephoneNumber;456456;
telexNumber;958;
postalAddress;456456;
initials; CASTRO;
employeeNumber;51932787;
title; F;
cn; SONIA ESPERANZA CASTRO TORRES;
mail; [email protected];
sn; TORRES;
userPassword;;
ibm-entryuuid;;
;;
dn; uid=456456,cn=users,dc=efsfb,dc=org,dc=co;
objectclass; top;
objectclass; person;
objectclass; organizationalPerson;
objectclass; inetOrgPerson;
uid; 456456;
userpassword;;
sn; OLIVERA;
givenName; MAURICIO;
cn; MAURICIO REINALES OLIVERA;
employeeType; CC;
mail; [email protected];
telephoneNumber;57383;
telexNumber;958;
postalAddress;19800101;
initials; REINALES;
employeeNumber;456456;
title; M;
ibm-entryuuid;;
;;
dn; uid=CC39681904,cn=users,dc=efsfb,dc=org,dc=co;
objectclass; top;
objectclass; person;
objectclass; organizationalPerson;
objectclass; inetOrgPerson;
uid; CC39681904;
givenName; MARIA DEL PILAR;
employeeType; CC;
telephoneNumber;217001;
telexNumber;958;
postalAddress;456456;
initials; ACUNA;
employeeNumber;456456;
title; F;
cn; MARIA DEL PILAR ACUNA PENA;
mail; [email protected];
sn; PENA;
userPassword;;
ibm-entryuuid;;
;;

你看,不是重复,有的可以有数据,有的没有,但共同点是分隔符“;”前面的第一个单词是一行

我怎样才能像这个示例一样将所有之前的数据转换为 csv

uid       employeeType            name                  email
mafsdfsf    cc                      maur                  mafsdf 
mafsdfsf   CC5dfgdfg8               monica               modfgfdg@g
blabla       blabla                 blabla              blabla

我已经用 awk、read IFS、readarray 进行了读取,但我无法达成这笔交易

感谢任何人都可以帮助我

但在本例中所有字段

答案1

使用perl。可能有一个 perl 模块来解析 LDAP 数据,但我没有费心去寻找一个,这很容易做到,不需要任何模块。

顺便说一句,您似乎想要制表符分隔的值,而不是逗号分隔的值。我已相应地命名了该脚本。如果您想要实际的 CSV,那么修改起来很容易(但请记住对每个字段加双引号 -dn特别是该字段已经包含逗号 - 或者只使用文本::CSV模块生成正确的 CSV 输出)。

$ cat ldap2tsv.pl 
#!/usr/bin/perl

use strict;

my @keys = qw(dn uid mail);                 # array of keys we're interested in
my $match = '^(' . join("|",@keys) . ');';  # turn @keys array into a regex
$match = qr($match);                        # pre-compile regex for performance

my %data = ();                              # hash to hold values for each key

print join("\t", @keys), "\n";              # print header line

while(<<>>) {
  next unless m/$match/;
  my ($key,$val) = split /\s*;\s*/;
  $data{$key} = $val;

} continue {
  if (m/^;;$/ || eof) {
    print join("\t", @data{@keys}), "\n";
    %data = ();
  };
};

首先创建一个包含我们感兴趣的键名称的数组,然后构建并预编译一个正则表达式以匹配数组中的键名称,并在标题行中打印键。 $match最终包含正则表达式^(dn|uid|mail);

然后它迭代输入的每一行,忽略与其中一个键不匹配的行。如果当前行匹配,则将其按;字符(带有可选的前导和/或尾随空格,\s*)拆分为标量变量$key$val。这些用于将当前行的数据插入到%data哈希中。

continue块在每一行之后执行 - 我在这里使用它来检查一行是否仅包含;;或我们位于文件末尾。如果是这样,则打印出当前数据行并清除 %data 中的当前值。

示例输出:

$ chmod +x ./ldap2tsv.pl
$ ./ldap2tsv.pl data.txt 
dn      uid     mail
uid=remisor1,cn=users,dc=efsfb,dc=org,dc=co     remisor1
uid=paciente1,cn=users,dc=efsfb,dc=org,dc=co    paciente1
uid=CC522496sdad48,cn=users,dc=efsfb,dc=org,dc=co       CC5dfgdfg8      [email protected]

如果您希望输出在良好对齐的列中,您可以将其通过管道传输到column -t.但请注意,这会将制表符转换为两个或多个空格。

$ ./ldap2csv.pl data.txt | column -t
dn                                                 uid         mail
uid=remisor1,cn=users,dc=efsfb,dc=org,dc=co        remisor1    
uid=paciente1,cn=users,dc=efsfb,dc=org,dc=co       paciente1   
uid=CC522496sdad48,cn=users,dc=efsfb,dc=org,dc=co  CC5dfgdfg8  [email protected]

my @keys = qw(dn uid mail);将行更改为并针对新数据集运行后my @keys = qw(uid employeeType givenName mail);,输出现在如下所示:

$ ./ldap2csv.pl data2.txt 
uid     employeeType    givenName       mail
456456456       CC      MONICA  [email protected]
456456456       CC      SONIA ESPERANZA [email protected]
456456  CC      MAURICIO        [email protected]
CC39681904      CC      MARIA DEL PILAR [email protected]

或采用良好的格式以供人类阅读column -s $'\t' -t

$ ./ldap2csv.pl data2.txt | column -s $'\t' -t
uid         employeeType  givenName        mail
456456456   CC            MONICA           [email protected]
456456456   CC            SONIA ESPERANZA  [email protected]
456456      CC            MAURICIO         [email protected]
CC39681904  CC            MARIA DEL PILAR  [email protected]

笔记:name您的数据中没有密钥。有一把givenName钥匙。我已经用它来代替了。与email- 没有email钥匙,但有mail钥匙相同。

相关内容