日付条件についてはわかりません。

日付条件についてはわかりません。

その人が過去1年以内に生まれていない場合は、person.csv(下)から行を削除しようとします。

データセット1:

"Index","User Id","First Name","Last Name","Date of birth","Job Title"
"1","9E39Bfc4fdcc44e","new, Diamond","Dudley","06 Dec 1945","Photographer"
"3","32C079F2Bad7e6F","Ethan","Hanson","08 Mar 2014","Actuary"
"2","aaaaaaa, bbbbbb","Grace","Huerta","21 Jan 2023","Visual merchandiser"

したがって、予想される出力は次のようになります(最後の行は1年以内に削除されました)。

"Index","User Id","First Name","Last Name","Date of birth","Job Title"
"1","9E39Bfc4fdcc44e","new, Diamond","Dudley","06 Dec 1945","Photographer"
"3","32C079F2Bad7e6F","Ethan","Hanson","08 Mar 2014","Actuary"

私はawkを使って次のことをしようとしています。

awk -F , '{print $5 ....}' person.csv > output.csv

ただし、各日付行を(今日から1年を引いた値)と比較する方法はわかりません。

データセット2:時には二重引用符で囲まれたフィールドに二重引用符があります(例:line1 field4)。

"Index","User Id","First Name","Last Name","Date of birth","Job Title"
"1","9E39Bfc4fdcc44e","new, Diamond","Dudley (aka "dud")","03 Oct 2023","Photographer"
"3","32C079F2Bad7e6F","Ethan","Hanson","03 Dec 2022","Actuary"
"2","aaaaaaa, bbbbbb","Grace","Huerta","21 Jan 2023","Visual merchandiser"

「sed」がこれを行うことができれば、私もそれについて開いています。どんな助けでもお願いします。ありがとうございます!

ベストアンサー1

仮定:

  • すべての列/フィールドは二重引用符で囲まれています。
  • 二重引用符はデータの一部として表示されません。それ以外の場合は、-F'"'フィールド区切り文字として基本文字以外の文字が必要です。
  • OP(オペレーティングシステム)はdateこの-dパラメータをサポートします(たとえば、16 Sep 2023OPシステムの「今日」date -d '-1 year' '+%Y%m%d'が生成される場合20220916
  • OPでは、締め切りは何でも可能であると述べたので(例:-1年、-7日など)、(オペレーティングシステム)を使用してdate特定の形式で期限を作成しますYYYYMMDD(そうでない場合は、コードを追加するする必要があります)awk。 「-1年」、「-7日」など様々な条件を処理できます。)

離れてawkいる:

cutoff=$(date -d '-1 year' '+%Y%m%d')                             # change '-1 year' to the desired condition;
                                                                  # alternatively: manually set to the desired date (in YYYYMMDD format)

awk -v cutoff="${cutoff}" -F'"' '                                 # set awk variable "cutoff" to the value of the OS variable of the same name
                                                                  # field delimiter is double quotes; this means data fields are even-numbered (eg, 5th field is the 10th "-delimited field)
BEGIN { mlist="JanFebMarAprMayJunJulAugSepOctNovDec" }
NR>1  { split($10,a,/[[:space:]]+/)                               # split 5th data field on spaces; a[1]=day a[2]=month a[3]=year
        m=sprintf("%02d", ( (index(mlist,a[2])+2) /3) )           # convert 3-letter month to 2-digit month
        if ( a[3] m a[1] > cutoff) next                           # if new date is greater than the cutoff then skip to the next line of input
      } 
1                                                                 # print the current line
' person.csv

これで以下が生成されます。

"Index","User Id","First Name","Last Name","Date of birth","Job Title"
"1","9E39Bfc4fdcc44e","new, Diamond","Dudley","06 Dec 1945","Photographer"
"3","32C079F2Bad7e6F","Ethan","Hanson","08 Mar 2014","Actuary"

パフォーマンスの観点...

この回答には単一のオペレーティングシステム呼び出しが必要で、date1つのファイル記述子を開く/閉じる必要があります(出力が別のファイルにリダイレクトされる場合は2つ)。

dateGillesの答えには、各入力行に対するオペレーティングシステムの呼び出しが必要です。そして各呼び出しに対してファイル記述子を開閉するのに費用がかかるオーバーヘッドですdate

テスト実行:

100K line file          # per comment from OP
GNU awk 5.1.0
GNU date 8.32
Ubuntu 20.04
i7-1260P

この答え:

real    0m0.198s        <<< 546 times faster
user    0m0.198s
sys     0m0.000s

ザイルズの答え:

real    1m48.229s       <<<
user    1m30.598s
sys     0m23.999s

両方の実行の出力はファイルに保存されます。diffaは、両方の出力ファイルに違いがないことを示しています(つまり、両方の答えは同じ結果セットを生成します)。


この場合、OPはすべてのフィールドが二重引用符で囲まれていることを示しています。

一部のフィールドを二重引用符で囲むことができない場合は、ペアへGNU awk's 'FPAT'の単一の呼び出しのみを使用して実行できますdate。たとえば、次のようになります。

cutoff=$(date -d '-1 year' '+%Y%m%d')

awk -v cutoff="${cutoff}" '
BEGIN { FPAT="([^,]+)|(\"[^\"]+\")"
        mlist="JanFebMarAprMayJunJulAugSepOctNovDec"
      }
NR>1  { f5=$5
        gsub(/"/,"",f5)                                           # strip double quotes from 5th data field
        split(f5,a,/[[:space:]]+/)                                # change from 10th field to 5th field
        m=sprintf("%02d", ( (index(mlist,a[2])+2) /3) )
        if ( a[3] m a[1] > cutoff) next
      }
    1
' person.csv

上記と同じテスト基準を使用して、この回答の実行時間は次のとおりです。

real    0m0.861s        <<<
user    0m0.850s
sys     0m0.009s

FPAT(代わりに-F'"')入力解析に基づくと、実行時間は約4倍になりますが、それでも108秒よりはるかに高速です。

おすすめ記事