【问题标题】:Control file based attribute population : Unix shell基于控制文件的属性填充:Unix shell
【发布时间】:2020-10-24 05:21:45
【问题描述】:

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

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

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

源 1 正在发送以下格式的 input.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 代码。我们可以用一个脚本来完成它,它也可以用于任何新的未来资源吗?

【问题讨论】:

  • 输入是否像示例数据中所示的逗号后的间距一样反复无常?还是逗号后总是有空格,还是逗号后没有空格?

标签: unix awk scripting cut


【解决方案1】:

在这种特殊情况下,您可以检查行中的字段数(假设文件的所有行具有相同的字段数)(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"]];
 }

【讨论】:

    【解决方案2】:

    这个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,
    

    【讨论】:

      猜你喜欢
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-16
      相关资源
      最近更新 更多