基于控制文件的属性填充:Unix shell



我有一个控制文件header.cntrl.它有header的详细信息。下面的示例...

cat header.cntrl
id, name, age, location, phone number

现在我从不同的来源获取文件,

源 1 正在发送以下格式的输入.dat文件

cat input.dat
id, name, age, location, status, phone number
1,Abc, 34,India, active, 9999999999

源 2 正在按以下格式发送数据

cat input_2.dat
id, age, name, qualification, status, phone number, location
2,24,xyz, L L B, Active, 88888-88888, India

因此,不同的来源正在发送不同格式的文件。我们需要将这些输入文件转换为 header.cntrl 文件格式。

我正在使用 awk 代码尝试这样做,但对于每个源,我需要编写一个 awk 代码。 我们可以使用一个脚本来做到这一点,该脚本也可以用于任何新的未来源吗?

reformat_data脚本可以重新格式化两种"非标准"输入格式和任何将来的源格式。关键思想是使用 Perl 哈希来存储适当的标题,并且只打印 header.cntrl 文件中指定的标题。

cat $* | perl -ne '
BEGIN {
@std_header = ("id","name","age","location","phone number");
print join(",", @std_header), ",n";
chomp($firstline=<>);
$firstline =~ s/,s+/,/g;
@inputfile_header=split(/,/, $firstline);
%hash=();
}
chomp;
@row = split(/,/);
$i=0;
for $cell (@row) {
$cell =~ s/s+//;
$header=$inputfile_header[$i];
$hash{$header} = $row[$i];
$i++;
}
foreach $cell (@std_header) {
print "$hash{$cell},";
}
print "n";
'

下面是使用两个示例输入文件运行reformat_data脚本的结果:

cat input.dat
id, name, age, location, status, phone number
1,Abc, 34,India, active, 9999999999
reformat_data input.dat
id,name,age,location,phone number,
1,Abc,34,India,9999999999,
cat input_2.dat
id, age, name, qualification, status, phone number, location
2,24,xyz, L L B, Active, 88888-88888, India
reformat_data input_2.dat
id,name,age,location,phone number,
2,xyz,24,India,88888-88888,

在这种特殊情况下,您可以检查行中的字段数(前提是文件的所有行都具有相同数量的字段((awk 代码(:

{
n = split($0, a, "[ t]*,[ t]*");
if (n < 7) {
print a[1] ", " a[2] ", " a[3] ", " a[4] ", " a[6];
}
else {
print a[1] ", " a[3] ", " a[2] ", " a[7] ", " a[6];
}
}

更复杂的解决方案是使用第一行作为键标识符,并"按名称"获取其余字段:

{
n = split($0, a, "[ t]*,[ t]*");
if (FNR == 1) {
for (i = 1; i <= n; ++i) {
lbl[a[i]] = i;
}
}

print a[lbl["id"]] ", " a[lbl["name"]] ", " a[lbl["age"]] ", " a[lbl["location"]] ", " a[lbl["phone number"]];
}

最新更新