マスターファイルに基づいて、さまざまなバージョンのテキストファイルのタイトルとデータを並べ替えます。

マスターファイルに基づいて、さまざまなバージョンのテキストファイルのタイトルとデータを並べ替えます。

参照マスターファイルで指定されたフィールドの順序に従って、パイプで区切られた複数のテキストファイルのデータ(タイトルと詳細)を並べ替え、シェルスクリプトを使用して単一の出力ファイルを生成したいと思います。以下のコードがありますが、期待どおりに動作しません。 while ループはマスターから列の順序を取得し、並べ替えます。ただし、考慮すべき次の機能があります。シェルスクリプト/awkでソリューションを探す

参照マスターファイルと比較して入力ファイルに欠落しているか、新しい列がある可能性があります。参照マスターファイルの順序は後で変更することができ、列は任意の場所から追加または削除できます。複数の入力ファイルを受け入れます。

入力ファイルAの例:

Name|Amount|Vehicle|City|Visits|Indicator

Jack|123.22|Volkswagen|Altamonte|1|Y

Sam|23.1|Audi||3|N

|21.4|Ford|NewYork||Y

入力ファイルBの例:

Suffix|Name|Visits|Vehicle|State|Indicator|City|Gender

Mr|Jack|1|Volkswagen|NJ|Y|Hoboken|M

Mr|Rob|6|Buick||N|Stamford|

基本ファイルを参照してください。

ステータス|1

都市|2

車両|3

性別|4

名前|5

数量| 6

結果ファイル:

State|City|Vehicle|Gender|Name|Amount

|Altamonte|Volkswagen||Jack|123.22

||Audi||Sam|23.1

|NewYork|Ford|||21.4

NJ|Hoboken|Volkswagen|M|Jack|

|Stamford|Buick||Rob|

シェルスクリプト:

/*Comment::Reads the input column names and assign number based on order for*/
/*Comment::each column in the input file.*/
cat infile.out | head -1 | tr -s '|' '\n' | cat -n > infile_tmp.out
rm -f final.out

/*Comment:compare the master file column names with input file column names and 
/*Comment:get the column number from master file*/ 
while read line; do 
touch final.out
vChkClmn=`echo $line | cut -d "|" -f1`
vMasterClm=`grep -i $vChkClmn infile_tmp.out | cut -d " " -f1`
echo "$vMasterClm" >> final.out
done < master_file.out

rm -f final_master_list.out
echo `cat final.out` | sed 's/[^ ]* */\$&/g' | sed 's/ /\,/g' > final_master_list.out
vOrder=`cat final_master_list.out`
echo "Value of order is $vOrder"
awk -F\| '{print '$vOrder'}' OFS=\| infile.out

ベストアンサー1

#!/usr/bin/perl

use strict;

my $master = shift;
open(M,"<","$master") || die "couldn't open $master:$!\n";
chomp(my @master = split(/\|/,<M>));
close(M);

print join("|",@master),"\n";

my @fields=();
while (<>) {
  if ($. == 1) {
    chomp(@fields = split /\|/);
    next;
  };

  chomp(my @row = split/\|/);
  my @out = ();

  foreach my $m (@master) {
    my $o='';
    for (my $i=0; $i < $#row; $i++) {
      if ($fields[$i] eq $m) {
        $o = $row[$i];
      };
    }
    push @out, $o;
  };

  print join("|",@out),"\n";
} continue {
    close ARGV if eof; # reset the line counter after each input file
}

これは参照マスターファイルを読み取ります(ここでは〜しなければならないコマンドラインの最初の引数)をフィールド名(@master)を含む配列に分割します。

次に、残りのファイル名パラメータをすべて読み、次の手順を実行します。

  • ファイルの最初の行の場合は、行を配列に分割してフィールドヘッダーを取得します。@fields
  • それ以外の場合は、行を配列に分割して@row@masterとの各要素を繰り返します@row。その場で名前行要素の1つは@masterの要素と一致し、フィールドの要素を追加します。出力配列(@out)に追加し、それ以外の場合は空の文字列を追加します。
  • @out文字で連結された配列を印刷します|
  • 配列@outは各入力ラインで空になるようにリセットされます。

たとえば、別の名前で保存してrearrange.pl実行可能にし、chmod +x rearrange.pl次のように実行します。

$ ./rearrange.pl master.txt input1.txt input2.txt 
State|City|Vehicle|Gender|Name|Amount
|Altamonte|Volkswagen||Jack|123.22
||Audi||Sam|23.1
|NewYork|Ford|||21.4
NJ|Hoboken|Volkswagen||Jack|
|Stamford|Buick||Rob|

注:これは2つの入力ファイルに限定されません。一度に必要な数の入力ファイルを処理できます。 2つの制限があります。

  1. 基本参照ファイル(例master.txt:)〜しなければならないコマンドラインの最初のパラメータです。

  2. 入力ファイルが少なくとも1つ必要です。または入力ファイルはスクリプトにパイプする必要があります。

    注:1つのファイルのみを入力できます。管路- 複数のファイルがパイプで接続されている場合、スクリプトはどの行がヘッダー行で、どの行がデータ行かを知ることはできません。

おすすめ記事