次のように、XML形式の日付を含むテキストファイルがたくさんあります。
<DATA2020-04-13T08:59:05.427 />
次のように変更する必要があります。
<DATA>2020-04-13T08:59:05.427</DATA>
メモ:
日付と時刻は文字列ごとに異なり、変更できません。各行の前後にはXML形式のコンテンツが多く表示されます。また、Unixを使用するdate
ことはオプションではなく、実際にファイル内のXML文字列を変更する必要があります。
sed
//検索と置換を使用しようとしていますawk
。perl
おそらくワイルドカードを使用することもできます。誰でもこれを達成する方法を考えることができますか?
答え1
$ echo '<DATA2020-04-13T08:59:05.427 />' | sed -E 's/<DATA(20[^/]*) \/>/<DATA>\1<\/DATA>/'
<DATA>2020-04-13T08:59:05.427</DATA>
または、エスケープをバックスラッシュする必要がないように、=
区切り文字として代わりに使用してください。/
/
$ echo '<DATA2020-04-13T08:59:05.427 />' | sed -E 's=<DATA(202[^/]*) />=<DATA>\1</DATA>='
<DATA>2020-04-13T08:59:05.427</DATA>
これにより、読みやすくなります(もちろん、=
検索パターンと代替テキストのすべての文字をエスケープする必要があります)。
Perlでもほぼ同じ正規表現を使用できます(主な違いは、\1
Perlでキャプチャグループを参照する方が良いと正確です)。区切り演算子の$1
より多くのオプションがあります(例:Match pair sum)。s
{
}
$ echo '<DATA2020-04-13T08:59:05.427 />' |
perl -pe 's{<DATA(202[^/]*) />}
{<DATA>$1</DATA>}'
<DATA>2020-04-13T08:59:05.427</DATA>
Perlには、角かっこ式と一緒に、または角括弧式内でエスケープされないスペース(改行を含む)を/x
無視する修飾子があります。コメント\
も無視します#
。その目的は、コードでより読みやすく、文書化された正規表現を簡単に作成できるようにすることです。
man perlre
Perl正規表現の詳細については、参考資料を参照してください。
答え2
ERE 認識 sed -E
(例: GNU または BSD sed) を使用してください。
$ sed -E 's:<(DATA)([^ ]+) />:<\1>\2</\1>:' file
<DATA>2020-04-13T08:59:05.427</DATA>
それ以外の場合は、すべてのUnixシステムのすべてのシェルでsedを使用してください。
$ sed 's:<\(DATA\)\([^ ]*\) />:<\1>\2</\1>:' file
<DATA>2020-04-13T08:59:05.427</DATA>
答え3
使用幸せ(以前のPerl_6)
raku -pe 's:g/ \<DATA ( <+[0..9]+[-T:.]>+ ) \s\/\> /{"<DATA>"~$0~"</DATA>"}/;'
または
raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = ["<DATA>"~$0~"</DATA>"];'
入力例:
<DATA2020-04-13T08:59:05.427 />
出力例:
<DATA>2020-04-13T08:59:05.427</DATA>
上記はコード化された答えです。幸せ、Perl プログラミング言語ファミリーのメンバーです。上記の2つの例は、注目すべき4つの一般的な特徴を共有しています。
バックスラッシュ文字を推測する必要はありません。バックスラッシュ文字でない場合
<alnum>
(英数字または下線)、エスケープする必要があります。/g
今のような正規表現修飾子は、書式global
の先頭の直後にコロンが続きます。または有効です。s///
s
s:global
s:g
Perlの
/x
修飾子はRakuのデフォルトです(正規表現原子間の空きスペースを許可します)。Rakuの文字列連結は、
~
チルダを使用して行われます。
上記の両方の例は、列挙された文字クラスを使用します<+[0..9]+[-T:.]>
。これは非常に簡単に数字[ 0..9
]に4つの文字[ -
T
:
.
]を加えたものです。また、上記の最初の例は伝統的なs///
代替イディオムに従いますが、上記の2番目の例はRakuの新しい「バックスラッシュなし」代替形式(=
中間に等号を含む)を使用しています。できます。
最後に、日付/時刻の抽出/修正に興味がある場合は、Rakuは以下を扱いました。
~$ echo '<DATA2020-04-13T08:59:05.427 />' | raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = [DateTime($0~"Z")];'
2020-04-13T08:59:05.427000Z
~$ echo '<DATA2020-04-13T08:59:05.427 />' | raku -pe 's:g[ "<DATA" ( <+[0..9]+[-T:.]>+ ) " />" ] = [DateTime(now) - DateTime($0~"Z")];'
54862286.622457
https://docs.raku.org/言語/regexes#Enumerated_character_classes_and_ranges
https://docs.raku.org/routine/DateTime
https://raku.org