web-dev-qa-db-ja.com

「sed」コマンドを使用してインプレースで日付形式を変更する

2016-Dec-24または2016-12-24がある場所のテキストの日付を変更しようとしています。24/12/2016のように置き換えなければなりません。

sed -iを使用してこれを行う方法はありますか?

入力例:

休日または儀式の宗教団体の日付追記* Rosh Hashanah(新年)ユダヤ人2014年9月25日-2014年9月26日オブザーバーの指定された非稼働日ナバラトリ/ダッセラヒンドゥー2014年9月

* Yom Kippur(贖罪の日)ユダヤ人2014年10月4日、オブザーバーの指定された非稼働日

スポンサー付き会議タイトル場所会議日2017 IEEEセンサーアプリケーションシンポジウム(SAS)米国2017-03-13、2017-03-14、2017-03-15 2017医療測定およびアプリケーションに関するIEEE国際シンポジウム(MeMeA)米国2017-05 -07 to 2017-05-10 2017 IEEE International Instrumentation and Measurement Technology Conference(I

これは、私がこれまでに試したことです。

sed -i -e 's/\([0-9]\{4\}\)-\(01|Jan\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(02|Feb\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(03|Mar\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(04|Apr\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(05|May\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(06|Jun\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(07|Jul\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(08|Aug\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(09|Sep\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(10|Oct\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(11|Nov\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
sed -i -e 's/\([0-9]\{4\}\)-\(12|Dec\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1
6
Alina Gorgovan

GNU date(Linuxシステムのデフォルト))へのアクセス権がある場合は、次のことができます。

$ sed -E 's/(.*)-([a-z]+)(.+)/\2\3-\1/i' file | 
    while read d; do date -d "$d" +%d/%m/%y; done
24/12/16
24/12/16

2016-Dec-24のような行をDec-24-2016に変更します(GNU dateが理解できる形式)、2016-12-24のような行を残します(形式GNU日付はすでに理解)だけで、次に各行を入力日付文字列としてdateに渡します。これはインプレースでは行われず、sed -iを使用しませんが、ほぼ間違いなく最も簡単な方法です。

本当にを使用してsedを実行する必要がある場合は、すべての月と対応する数値のリストを作成できます。

$ for m in {1..12}; do printf '%s %s\n' "$m" $(date -d "$m/1/2016" +%b); done
1 Jan
2 Feb
3 Mar
4 Apr
5 May
6 Jun
7 Jul
8 Aug
9 Sep
10 Oct
11 Nov
12 Dec

それをmonthsとして保存し、それを繰り返してファイルを変更します。

while read num mon; do 
    sed -Ei "s/$mon/$num/; s#(.*)-(.*)-(.*)#\3/\2/\1#" file
done < months 

または、sed実装で別の-eが必要な場合:

while read num mon; do 
    sed -i -e "s/$mon/$num/" -Ee 's#(.*)-(.*)-(.*)#\3/\2/\1#' file
done < months 

最初の置換では、すべてのアルファベットの月の名前を対応する番号に置き換えます。2番目の置換では、目的の形式になるように移動します。

5
terdon

正規表現に関して間違っていると私が思う唯一のことは、基本(BRE)モードでは、|がリテラルであることです。これを論理ORにするためには\|が必要です(つまり、\(01\|Jan\)など)。

お使いのバージョンが-eをサポートしている場合、sedを複数回呼び出す正当な理由はありません。-e <expr1> -e <expr2> ...を1回の呼び出しでチェーンするだけです。そう

sed -i \
  -e 's/\([0-9]\{4\}\)-\(01\|Jan\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(02\|Feb\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(03\|Mar\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(04\|Apr\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(05\|May\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(06\|Jun\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(07\|Jul\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(08\|Aug\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(09\|Sep\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(10\|Oct\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(11\|Nov\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' \
  -e 's/\([0-9]\{4\}\)-\(12\|Dec\)-\([0-9]\{2\}\)/\3\/\2\/\1/g' $1

ただし、これを行うにはよりエレガントな方法があります。たとえば、Perlでstrptimeおよびstrftime関数を使用します(たとえば、Time::Pieceモジュールによって提供されます)。

Perl -i -MTime::Piece -pe '
  s|\d{4}-\d\d-\d\d?|Time::Piece->strptime($&, "%Y-%m-%d")->strftime("%Y/%m/%d")|ge;
  s|\d{4}-...-\d\d?|Time::Piece->strptime($&, "%Y-%b-%d")->strftime("%Y/%m/%d")|ge;
' file
1
steeldriver
sed -r -i '
/([0-9]{4})-([[:alpha:]]{3})-([0-9]{2})/ {
    s#([0-9]{4})-Jan-([0-9]{2})#\2/01/\1#g
    s#([0-9]{4})-Feb-([0-9]{2})#\2/02/\1#g
    s#([0-9]{4})-Mar-([0-9]{2})#\2/03/\1#g
    s#([0-9]{4})-Apr-([0-9]{2})#\2/04/\1#g
    s#([0-9]{4})-May-([0-9]{2})#\2/05/\1#g
    s#([0-9]{4})-Jun-([0-9]{2})#\2/06/\1#g
    s#([0-9]{4})-Jul-([0-9]{2})#\2/07/\1#g
    s#([0-9]{4})-Aug-([0-9]{2})#\2/08/\1#g
    s#([0-9]{4})-Sep-([0-9]{2})#\2/09/\1#g
    s#([0-9]{4})-Oct-([0-9]{2})#\2/10/\1#g
    s#([0-9]{4})-Nov-([0-9]{2})#\2/11/\1#g
    s#([0-9]{4})-Dec-([0-9]{2})#\2/12/\1#g
}
s#([0-9]{4})-([0-9]{2})-([0-9]{2})#\3/\2/\1#g
' file
0
mug896