2013-08-26 12 views
9

bashスクリプトを使用して、テーブルを含むHTMLを.csvファイルに変換しようとしています。sedまたはawkを使用して日付形式を修正する

これまでのところ、私はacomplishedてきた次のステップ:

  1. はと(
  2. は、すべての空白行を削除する(sed 's/[ \t]//g'で)すべてのスペースとタブを削除
  3. dos2unix付き)Unixのフォーマットに変換しますsed ':a;N;$!ba;s/\n//g')(HTMLファイルにテーブルの各セルに空白行があるので、これは必要です。これは自分のものではありません)
  4. 不要な<td><tr>タグを削除します。sed 's/<t.>//g'
  5. のend-of-line(\n)文字(sed 's/<\/tr/\n/g'付き)もちろん

</tr>を交換し

  • sed 's/<\/td/,/g'で( '' で</td>を交換し、私はすべてこの中に入れていますパイプライン。これまでのところ、それは素晴らしい仕事です。最終的なステップは次のとおりです。テーブルには日付が付いたカラムがあります。フォーマットはdd/mm/yyyyです。yyyy-mm-ddに変換したいと思います。

    (簡単な)方法(sedまたはawk)がありますか?

    (全体sed配管後の)データサンプルは:

    500,2,13/09/2007,30000.00,12,B-1 
    501,2,15/09/2007,14000.00,8,B-2 
    

    期待される結果

    500,2,2007-09-13,30000.00,12,B-1 
    501,2,2007-09-15,14000.00,8,B-2 
    

    私はこのデータをインポートする必要があるので、私はこれを行うために必要な理由がありますMySQLへ。私はExcelでファイルを開き、フォーマットを手で変更することができましたが、私はそれをスキップしたいと思います。

  • 答えて

    7

    Awkはかなり簡単にこの作業を行うことができます。

    awk ' 
        BEGIN { FS = OFS = "," } 
        { split($3, date, /\//) 
         $3 = date[3] "-" date[2] "-" date[1] 
         print $0 
        } 
    ' infile 
    

    それが得られます。

    500,2,2007-09-13,30000.00,12,B-1 
    501,2,2007-09-15,14000.00,8,B-2 
    
    4
    sed "s:,\([0-9]\+\)/\([0-9]\+\)/\([0-9]\+\),:,\3-\2-\1,:" 
    
    4

    awkは、このために働くだろう:

    echo 08/26/2013 | awk -F/ '{printf "%s-%s-%s\n",$3,$2,$1}' 
    

    をこれらのでしょう一つとして、 bashののみのオプション:あなたはサブシェルがパイプラインの最後のコンポーネントのために使用されていないkshを、使用してしまった場合

    IFS=/ read m d y < <(echo 08/26/2013); echo "${y}-${m}-${d}" 
    IFS=/ read m d y <<< "08/26/2013"; echo "${y}-${m}-${d}" 
    

    が、これも同様に動作するはずです:bash最近で

    echo 08/26/2013 | IFS=/ read m d y; echo "${y}-${m}-${d}" 
    

    、スクリプト内でshopt -s lastpipeを使用して上記の呼び出しを有効にすることもできますが、コマンドラインでは機能しません(下記のコメントの@ mklement0のおかげで)。

    私はAWKに補正

    +0

    この場合、 'read'が_subshel​​l_で動作するので、' read'ベースのコマンドは動作しません。 'echo '08/26/2013 'を使用してください。 {IFS = /読み取りm d y;エコー "$ {y} - $ {m} - $ {d}"; } 'または ' IFS =/read m d y <<< '08/26/2013';エコー "$ {y} - $ {m} - $ {d}" ' – mklement0

    +1

    @ mklement0ああ、そうですね。しかし、 'ksh'でもうまくいくでしょう。別の代替手段は、( 'echo'がサブシェルにあるかもしれませんが)サブシェルを避けるために 'IFS =/read m d y <(echo 08/26/2013)'でしょう。 – twalberg

    +0

    良い点ですが、ここではおそらく '<<<'が最も効率的です。 Bash v4.2 +では、 'shopt -s lastpipe'を使うこともできます(ただし、スクリプト内のみ)。解決策の1つで回答を更新することをお勧めしますか? – mklement0

    7
    sed -E 's,([0-9]{2})/([0-9]{2})/([0-9]{4}),\3-\2-\1,g' 
    
    +0

    これを最初のパスの例として貼り付けて、物事を進めていくと、それはそのままの状態になりました!ありがとうございました! – Matthew

    1

    ...残りの部分とそれを統合する方法を見つけ出すためにあなたにそれを任せるあなたはYYYY-MM-DD(ないYYYY-DD-MMを求めると仮定)

    echo 08/26/2013 |

    2

    これまでのところ、すべての回答はOPの問題に特化しています。もちろん

    awk 'BEGIN{FS=","} 
        { 
         "date -d\"" $3 "\" +%Y-%m-%d" | getline mydate; 
         print $1 "," $2 "," mydate "," $4 "," $5 "," $6 
        }' 
    

    入力日付形式はdateによって処理されている場合のみであるとして、このアプローチは動作します:ここで(-dオプションのためのGNUを)実行しているより一般的なアプローチ、dateawkを通してです。 AFAICSこれは残念なことにdd/mm/yyyyのケースではありません。 1つはother commandsよりdate(テストされていない)よりもお試しいただけます。

    編集:mklement0のコメントを実装しました。

    Edit2:実際には、これはmawk(Debianのデフォルトのawkの実装)で動作しません。可能であれば、明らかな解決策はgawkをインストールすることです。

    +1

    ++ですが、 '-d'のために_GNU_' date'が必要であることを言及する必要があります。同様に、 '|&'はGNU Awk拡張ですが、ここでは実際には必要ではありません: '|'これはすべてのAwksで動作します。 最後に、視覚的にわかりやすくするため、またAwkの文字列連結がシェル内で異なる方法で動作することを示すために、連結する文字列の間にスペースを使用することをお勧めします。例えば、 "date -d" "$ 3" '+%Y-%m-%d "'(スペースを埋め込んだフィールドに対してガードするためにシングルクォートを追加しました) – mklement0

    +1

    @ mklement0:あなたの提案をありがとう、私は答えを編集しました。一重引用符は使用できません。エスケープされた二重引用符で置き換えます。 –

    +1

    答えを更新してくれてありがとう、そして私の一重引用符の間違いをキャッチしてくれてありがとう(ちょうどそれを明示する:Awkスクリプトの中で一重引用符を使うことはできない。 – mklement0

    関連する問題