数千行のtxtを行と列に解析します。

数千行のtxtを行と列に解析します。

現在のドキュメントには、何千人ものユーザーの名前、資格情報、役割、権限がリストされています。 .xlsに渡されましたが、行と列が正しい形式でソートされていません。 awkとsedを使用して元のファイルの形式を再指定しましたが、次の一貫した形式の行がたくさんあります。

ID       ;email                     ;role  ;privilege ;access-to
8charID1 ;[email protected] ;usr   ;read      ;finance ;HR ;accounting; dev
8charID2 ;[email protected] ;mgr   ;rwx       ;finance
8charID3 ;[email protected] ;usr   ;rx        ;marketing ;dev ;doc
.
.
n x 1,000 number of users

しかし、次の段階で詰まった。

目的:アクセスされたフィールドが複数ある場合(たとえば、行1または行3)、行を再印刷し、アクセスされたフィールドの数に基づいて以前のすべてのフィールドを再印刷し、アクセスされたフィールドを単一の列に並べ替えます。

ID       ;email                     ;role  ;privilege ;access-to
abcuser1 ;[email protected] ;usr   ;read      ;finance
abcuser1 ;[email protected] ;usr   ;read      ;HR
abcuser1 ;[email protected] ;usr   ;read      ;accounting
abcuser1 ;[email protected] ;usr   ;read      ;dev
user2def ;[email protected] ;mgr   ;rwx       ;finance
zyxuser3 ;[email protected] ;usr   ;rx        ;marketing
zyxuser3 ;[email protected] ;usr   ;rx        ;dev
zyxuser3 ;[email protected] ;usr   ;rx        ;publication
.
.
.
n x 1,000 number of users

答え1

awk -F';' -v OFS=';' '
    { for (i=5; i<=NF; i++) print $1,$2,$3,$4,$i }
' file

出力

ID       ;email                     ;role  ;privilege ;access-to
8charID1 ;[email protected] ;usr   ;read      ;finance 
8charID1 ;[email protected] ;usr   ;read      ;HR 
8charID1 ;[email protected] ;usr   ;read      ;accounting
8charID1 ;[email protected] ;usr   ;read      ; dev
8charID2 ;[email protected] ;mgr   ;rwx       ;finance
8charID3 ;[email protected] ;usr   ;rx        ;marketing 
8charID3 ;[email protected] ;usr   ;rx        ;dev 
8charID3 ;[email protected] ;usr   ;rx        ;doc

答え2

Glennのソリューションと同じ基本的なアイデアがありますが、Perlでは次のようになります。

$ perl -F";" -lane '$"=";";print "@F[0..3];", $_ for @F[4..$#F]' file 
ID       ;email                     ;role  ;privilege ;access-to
8charID1 ;[email protected] ;usr   ;read      ;finance 
8charID1 ;[email protected] ;usr   ;read      ;HR 
8charID1 ;[email protected] ;usr   ;read      ;accounting
8charID1 ;[email protected] ;usr   ;read      ; dev
8charID2 ;[email protected] ;mgr   ;rwx       ;finance
8charID3 ;[email protected] ;usr   ;rx        ;marketing 
8charID3 ;[email protected] ;usr   ;rx        ;dev 
8charID3 ;[email protected] ;usr   ;rx        ;doc

説明する

  • -a:Perlを同様に動作させ、awk自動的に各行を空白のフィールドに分割し(デフォルトでは参照-F@F、配列に保存します。
  • -e:コマンドラインにスクリプトを提供できます。
  • -n:入力ファイルを1行ずつ読みます。
  • -lprint:末尾の改行を削除し、各呼び出しに改行を追加します。
  • -F:と同様に、awk入力フィールドの区切り記号です。ここでは に設定しました;

もちろん、スクリプトは少し難しいですが、アルゴリズムは非常に簡単です。最初の4つのフィールドを印刷し、各フィールドに対して> 4を繰り返します。

  • $"=";": 特殊変数は$"リスト区切り文字です。これは、配列を印刷すると、配列の各要素間に印刷されます。ここでは;、必要に応じてフィールドリストを印刷できるように設定しました。

  • @F[0..3]:配列スライスです。配列の最初の4つの要素です@F;現在行の - 区切りフィールド)。

  • @F[4..$#F]:別の配列スライス。これは、5番目の要素から@F最後の要素($#arrayPerlの配列の最大インデックス)までです。

完全な印刷コマンドは単に寛容なPerlコマンドです:

## For each element of the array slice
foreach $field (@F[4..$#F]){
  ## print the first 4 fields and a ';', The fields 
  ## are printed separated by ";" because of the $" above.
  print "@F[0..3];";
  ## In the golfed version, the $_ is equivalent to $field here
  print "$field\n"
}

関連情報