7

日付をある形式から別の形式に変換しようとしています。たとえば、「2005 年 10 月 29 日」から 2005-10-29 に変換します。625 の日付のリストがあります。オークを使っています。

ほとんどの場合、変換は機能します。ただし、場合によっては変換がまったく行われず、(変換された) 日付を保持するはずの変数が未定義のままになることがあります。

これは常にまったく同じ行で発生します。これらの奇妙な行の日付に対して (Bash シェルから) 明示的に「date」を実行すると、問題なく動作します (日付は適切に変換されます)。-- 重要なのは、それらの行のテキストの内容ではありません。

この動作の理由と、スクリプトを修正するにはどうすればよいですか?
彼女は:

awk 'BEGIN { FS = "unused" } { 
  x = "undefined";
  "date \"+%Y-%m-%d\" -d " $1 | getline x ;
  print $1 " = " x
}' uBXr0r15.txt \
 > bug-out-3.txt

この問題を再現したい場合:

  1. このファイルをダウンロードします: uBXr0r15.txt
  2. Awk スクリプトを実行します。
  3. bug-out-3.txt で「undefined」を検索します。
    (「未定義」は、私のコンピューターで 122 回見つかりました。)

その後、スクリプトを再度実行すると、(私のコンピューターでは) bug-out-3.txt は変更されず、まったく同じ日付が未定義のままになります。

(Gawk バージョン 3.1.6、Ubuntu 9.10。)

敬具、マグナス

4

3 に答える 3

11

読み取りまたは書き込みのためにパイプまたはファイルを開くawkと、後者は最初に(内部ハッシュを使用して)同じ名前のパイプまたはファイルが(まだ)開いているかどうかをチェックします。その場合、パイプまたはファイルを再度開く代わりに、既存のファイル記述子を再利用します。

undefinedあなたの場合、最終的には実際には重複しているすべてのエントリ。それらが最初に検出されたとき(つまり、対応するコマンドdate "..." -d "..."が最初に発行されたとき)、適切な結果がに読み込まれxます。同じ日付の後続のオカレンスで、パイプがによって閉じられていても、元のパイプgetlineから2番目、3番目などの行を読み取ろうとします。その結果、パイプは割り当てられなくなります。datedatex

gawkマニュアルページから:

注:パイプ、コプロセス、またはソケットを使用してgetlineを実行する場合、またはループ内のprintまたはprintfから使用する場合は、close()を使用してコマンドまたはソケットの新しいインスタンスを作成する必要があります。AWKは、EOFを返すときに、パイプ、ソケット、またはコプロセスを自動的に閉じません。

close読んだ後は、毎回明示的にパイプを作成する必要がありますx

close("date \"+%Y-%m-%d\" -d " $1)

ちなみに、配管する前に配管しsortても大丈夫ですか、それとも元の注文/複製が必要ですか?uniq uBXr0r15.txtawk

于 2010-03-06T04:07:51.750 に答える
3

私はawkが大好きですが、これは必要ありません。

tr -d '"' < uBXr0r15.txt | date +%Y-%m-%d -f -

于 2010-03-06T04:02:23.163 に答える
3
 gawk 'BEGIN{
       m=split("January|February|March|April|May|June|July|August|September|October|November|December",d,"|")
       for(o=1;o<=m;o++){
          months[d[o]]=sprintf("%02d",o)
       }
       FS="[, ]"
    }
    {
      gsub(/["]/,"",$1)
      gsub(/["]/,"",$4)
      t=mktime($4" "months[$1]" "$2" 0 0 0")
      print strftime("%Y-%m-%d",t)
    }' uBXr0r15.txt

gawk 内ですべてを実行すると、外部コマンドを呼び出すよりも高速になります。

于 2010-03-06T04:25:37.920 に答える