次の形式のいくつかのフィールドを含むテキスト ファイルがあります。名前:電話:住所:生年月日:給与 生年月日の形式は mm/dd/yy です。現在の年から生年を差し引いて特定の人の年齢を計算する方法がわかりません。年齢を抽出して、特定の年齢グループと比較する必要があります。たとえば、50 です。いくつか試してみましたが、 awk -F: '{print $4-d}' "d=$(date)" filename のような奇妙な数字が表示されました
2 に答える
あなたは試してみたいかもしれません:
awk -F: -v year=$(date +"%Y") '{ split($4, dob, "/"); print $1, "is", year-dob[3], "years old" }' file.txt
編集1:
60歳未満の人のリストを印刷するには、次のことを試してください。
awk -F: -v year=$(date +"%Y") '{ split($4, dob, "/"); if (year-dob[3] <= 60) print $1 }' file.txt
説明:
の基本的な理解を前提としていawk
ます。この-v
オプションを使用awk
すると、シェルから変数を読み込むことができます。この場合、date +"Y"
単に現在の年を返します。フィールドを分割できる機能がありますawk
。split
この場合、日付を含む4番目のフィールドは/
、月/日/年を区切ります。split
物事を配列に分割します。この場合、配列に名前を付けましたdob
(生年月日)。3番目のフィールド(1つのインデックス付き)には、生年が含まれます。次に、その人の年齢が60歳以上であることを確認するための条件付きの簡単な計算を行います。彼が最初のフィールドに彼の名前を印刷している場合。
編集2:
あなたの質問についてもう少し考えてみると、上記のアプローチが実際に物事を完全に計算していないことは明らかです。それは大雑把な迅速な仕事でした(ごめんなさい、まあ...)。ですから、これがはるかに正確な更新バージョンです。次のように実行します:
awk -f script.awk file.txt
内容script.awk
:
BEGIN {
FS=":"
"date +\"%s\"" | getline cdate
}
{
rdate = gensub(/([0-9]+)\/([0-9]+)\/([0-9]+)/, "\\3-\\1-\\2", "g", $4)
cmd = "date -d " rdate " +\"%s\""
while (( cmd | getline result ) > 0 ) {
if ((cdate - result) / 31556926 <= 60) {
print $1
}
}
}
編集3:
または、外部コマンドとgetlineなし:
BEGIN {
FS=":"
cdate = systime()
}
{
rdate = gensub(/([0-9]+)\/([0-9]+)\/([0-9]+)/, "\\3 \\1 \\2 0 0 0", "g", $4)
result = mktime(rdate)
if ((cdate - result) / 31556926 <= 60) {
print $1
}
}
GNU awk を使用する (サンプル入力と期待される出力を提供しなかったため、動作するはずですが、テストされていません):
BEGIN{
FS = ":"
nowSecs = systime()
nowYear = strftime("%Y",nowSecs)
nowDay = strftime("%j",nowSecs)
}
{
# input date format is MM/DD/YY
dobSpec = gensub(/([0-9]+)\/([0-9]+)\/([0-9]+)/, "\\3 \\1 \\2 0 0 0", "", $4)
dobSecs = mktime("20" dobSpec)
if ( (dobSecs > nowSecs) || (dobSecs < 0) ) {
# guessed the wrong century so try again
dobSecs = mktime("19" dobSpec)
}
dobYear = strftime("%Y",dobSecs)
dobDay = strftime("%j",dobSecs)
diffYears = nowYear - dobYear
diffDays = nowDay - dobDay
age = diffYears + (diffDays >= 0 ? 1 : 0)
if ( age < 60 ) {
print
}
}
別の方法として、シェルの日付への外部呼び出しとそれに続く getline を使用しない @steve のソリューションは次のようになります。
BEGIN {
FS=":"
cdate = systime()
}
{
rdate = gensub(/([0-9]+)\/([0-9]+)\/([0-9]+)/, "\\3 \\1 \\2 0 0 0", "g", $4)
result = mktime(rdate)
if ((cdate - result) / 31556926 <= 60) {
print $1
}
}
年間秒数の概算を使用したくなかったので、それが機能しないエッジケースがあると思うので、そのルートには行きませんでした。@steve のオリジナルのように、上記の最初のソリューションで行ったように、入力年に欠落している世紀を提供するために、上記の 2 番目のソリューションを変更する必要があります。