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
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番目の置換では、目的の形式になるように移動します。
正規表現に関して間違っていると私が思う唯一のことは、基本(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
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