次のようにサンプルデータファイルを更新します。
empid;1001
empname;ABC
salary;3000
dept;ABC
age;24
dept;112
JOD;20170101
empid;A2001
salary;5000
dept;XYZ
age;27
JOD;20170303
age;92
empid;1002
empname;MAN
salary;11000
dept;SCI
age;30
dept;Geology
JOD;20180607
empid;1005
empname;NAME
salary;10200d
dept;XYZ
JOD;20161212
すべての属性を検索し、各属性の最初の項目を別のファイルにコピーする必要があります。出力は次のようになります。
empid;1001
empname;ABC
salary;3000
dept;ABC
age;24
JOD;20170101
empid;2001
salary;5000
dept;XYZ
age;27
JOD;20170303
empid;1002
empname;MAN
salary;11000
dept;SCI
age;30
JOD;20180607
empid;1005
empname;NAME
salary;10200
dept;XYZ
JOD;20161212
dept
2番目の発生は、各値セットにある場合は考慮してはいけません。
empid,empname,salary,dept,age,JOD.
現在、次のコードを使用しています。
awk -v FS=';' OFS=';'{
if ($1 == "empid" || $1 == "empname" || $1 == "salary" || $1 == "dept" || $1 == "age" || $1 == "JOD" ) print $0 }' FILE_NAME > NEW_FILE_NAME.
しかし、2回目の登場dept
も同様です。ご案内ください。
答え1
Kusalanandaが正確で、各従業員の記録がlineで始まると仮定すると、empid
次のawk
コマンドが機能します。
awk -F';' '$1=="empid" {delete a} !a[$1]++' input.txt > output.txt
これは、配列変数を使用してa
発生した属性名を追跡し、まだ属性名が見つからない場合にのみ現在行を印刷します。属性が見つかるたびに配列がempid
リセットされます。
より詳細な説明:
$1=="empid" {delete a}
a
新しいレコードが開始されるたびに配列が削除されます。!a[$1]++
awk
速記表記では、条件付き1
ルールの外側の部分は「この行を印刷します」を意味し、0
「印刷しない」を意味します。a[$1]++
「発生カウンタ」は、属性名の各値に対して増加し、ここでは「配列インデックス」として扱われます。- 評価
!a[$1]++
は最初配列項目の現在の値がゼロかどうか(つまり、属性がまだ見つかっていないかどうか)を確認し、print
trueの場合(否定演算子のおかげで)操作を実行し、カウンタをインクリメントします。それから(これは、Cスタイルのプログラミング言語でプレフィックス/サフィックスの増加がどのように機能するかと同じです。)したがって、そのプロパティがまだ見つからない場合は印刷されますが、それ以降の発生は無視されます。
ノートこのdelete a
ステートメントは2012 POSIX標準で許可されている構文に従い、上記はGNUとGNUに適用されますが、awk
Stéphane Chazelasmawk
はnawk
この構文をサポートしない実装について次のように述べました。
delete a
と交換する必要があります
split("",a)
答え2
これは次の基本的なアイデアです。AdminBeeのソリューション、少し優雅ですが(何の理由もなくすべての値をメモリに保存します)、少し短いです。
gawk -F';' '$1=="empid"{i=$2} ++a[i][$1]==1' file
最初のフィールドがある場合は、それをi
従業員IDに設定しますempid
。その後、awkで素晴らしい小さなトリックを活用します。式がtrueと評価されると、awkはその行を印刷します。したがって、最初のキーが現在の行(として保存されている)で、2番目のキーが現在の行()の最初のフィールドである2次元配列a[i][$1]
の要素です。 1つが追加されるため、各特定のフィールドが最初に表示されたときにのみ式がtrueになります。これが真かどうかだけを印刷するので、このコマンドは各IDの最初の項目を印刷します。empid
i
a[i][$1]
++
++a[i][$1]==1
empid
これにはGNU awkが必要です。