awkで日付から誤った応答を受け取る

awkで日付から誤った応答を受け取る

インターフェイスの最後の入力と出力を表示するCiscoスイッチの出力を便利な形式に変換できるスクリプトを作成しようとしています。これは、たとえば、過去6ヶ月間、どのインターフェイスが使用されていないかを知ることができるようにするためです。シスコでは、インターフェイスへの最後の入力が10w4d

これまでに得たのは、次のような入力ファイルです。

FastEthernet0/4,3 days ago,3 days ago
FastEthernet0/8,46 years ago ,46 years ago 
FastEthernet0/10,46 years ago ,46 years ago 
FastEthernet0/11,46 years ago ,46 years ago 
FastEthernet0/12,08:47:53,04:00:32
FastEthernet0/13,1 year ago 46 weeks ago ,1 year ago 46 weeks ago 
FastEthernet0/14,46 years ago ,46 years ago 
FastEthernet0/15,13 weeks ago 4 days ago ,13 weeks ago 4 days ago 
FastEthernet0/16,46 years ago ,46 years ago 
FastEthernet0/18,46 years ago ,46 years ago 
FastEthernet0/19,46 years ago ,46 years ago 
FastEthernet0/20,46 years ago ,46 years ago 
FastEthernet0/22,46 years ago ,1 year ago 50 weeks ago 
FastEthernet0/24,46 years ago ,46 years ago

有効な日付を取得できるように、Never Last Input and Output状態のすべてのインターフェイスを46年前に設定しました。はい、これを考慮できる稼働時間の記録があります。

私の問題は、現在有効な日付に変換しようとしていることです。これはawk正常に動作します。xargs

awk -F, '{print $2}' tst | xargs -i date -d "{}" +%Y-%m-%d

私は次のような答えを受けました。

2016-08-18
1970-08-21
1970-08-21
1970-08-21
2016-08-21
2014-10-03
1970-08-21
2016-05-18
1970-08-21
1970-08-21
1970-08-21
1970-08-21
1970-08-21
1970-08-21

しかし、これを行うと、次のような結果が出るようです。

awk -F, -v OFS="," '{
    cmd2=("date \"+'%Y-%m-%d'\" -d \""$2 "\"")
    cmd2|getline d2
    print cmd2,d2
}' tst

私は次のような答えを受けました。

date "+%Y-%m-%d" -d "3 days ago",2016-08-18
date "+%Y-%m-%d" -d "46 years ago ",1970-08-21
date "+%Y-%m-%d" -d "46 years ago ",1970-08-21
date "+%Y-%m-%d" -d "46 years ago ",1970-08-21
date "+%Y-%m-%d" -d "08:47:53",2016-08-21
date "+%Y-%m-%d" -d "1 year ago 46 weeks ago ",2014-10-03
date "+%Y-%m-%d" -d "46 years ago ",2014-10-03
date "+%Y-%m-%d" -d "13 weeks ago 4 days ago ",2016-05-18
date "+%Y-%m-%d" -d "46 years ago ",2016-05-18
date "+%Y-%m-%d" -d "46 years ago ",2016-05-18
date "+%Y-%m-%d" -d "46 years ago ",2016-05-18
date "+%Y-%m-%d" -d "46 years ago ",2016-05-18
date "+%Y-%m-%d" -d "46 years ago ",2016-05-18
date "+%Y-%m-%d" -d "46 years ago ",2016-05-18

cmd2ちょうどコマンドに追加して、何をするのかを確認しました。printこのコマンドを実行すると、正しい日付が表示されます。

簡単な内容が欠けているようですが、3〜4時間繰り返して試した結果、もう一度見てみたいです。

誰かが私に正しい方向を教えてもらえますか?

書き直す! Stephenも指摘したように、入力ファイルの3行だけで問題はありませんでした。テストされていないシナリオを投稿して申し訳ありません。

ベストアンサー1

これを行うとき:

cmd = "some command"
cmd | getline d2
cmd | getline d2

awk最初のものはgetline出力の最初の行(レコード)を取得し、2番目は2番目の行を取得します。出力の終わりに達するとゼロが返されます。cmdcmdgetlinegetline

あなたの場合、cmd = "date -d \"46 years ago\""コマンドは1行だけを出力するので、最初のコマンドはその行と正数をgetline返しますが、2番目のコマンドは到着するので0を返し、変更されません。d2eofd2

これには次のものが必要です。

 cmd | getline d2; close(cmd)

だからcmd毎回実行する必要があります。

または、同じパラメータで同じコマンドを複数回実行しないように、出力をハッシュに保存しますcmd

if (!($2 in cache)) {cmd=...; cmd | getline cache[$2]; close(cmd)}
print cache[$2]

cmd多くのファイル記述子を開かない場合は、その場所を閉じることをお勧めします。


close(cmd)when のあいまいさは とcmdに両方適用されます。閉じるかどうかgetline < cmdcmd | getlinecmd 注文するまたはcmd 文書それとも両方?

$ cat test.awk
BEGIN{
  OFS=","
  getline a1 < "uname"
  "uname" | getline b1
  close("uname")

  getline a2 < "uname"
  "uname" | getline b2
  print a1,b1,a2,b2
}
$ echo test > uname
$ mawk -f test.awk
test,Linux,test,Linux
$ bwk-awk -f test.awk
test,Linux,test,Linux
$ gawk -f test.awk
test,Linux,,Linux
$ busybox awk -f test.awk
test,,test,

(Brian Kernighan(at)が管理し、bwk-awkSolarisやFreeBSDなどに基づくawkの実装と同様に動作します。)kawknawkawk

"uname"busybox awkを使用してファイルとコマンドを同時に使用できない方法と閉じないgetline方法を学びます。close("uname")uname 文書存在するgawk

したがって、同じ名前のファイルとコマンドを同時に使用しないことをお勧めします。"\n"開始または終了に追加できます。注文するに関連する可能性を下げること文書

良い:

 awk 'BEGIN {getline foo < $ENVIRON["FILE"]; "uname\n" | getline system}'

$FILEもしそうなら、この問題は避けることができるでしょうuname$FILEそうではないかもしれませんが、uname<newline>可能性は低いです)。

おすすめ記事