
次のようなテキストがあると想像してください。
2012年と2013年のクイックブラウンフォックスジャンプ
そして、私は「fox」から 4 つの数字を含む部分を削除したいのですが、最初の部分だけ削除したいので、次のようになります。
クイックブラウンと2013
こんな感じです...:
echo "2012年と2013年にクイックブラウンフォックスがジャンプ" \ | sed "s/fox.*\([0-9]\{4\}\)//g"
...次のことが起こります:
クイックブラウン
したがって、4 つの数字の最後の出現を含むすべてが削除されました。
何か案は?
答え1
で使用される POSIX 正規表現sed
(「基本」バージョンと「拡張」バージョンの両方) は、非貪欲一致をサポートしていません。 ([^0-9]*
の代わりにを使用するなどの回避策はいくつかあります.*
が、入力が大きく変化する場合は信頼性が低くなります。)
必要なことは、Perl で?
非貪欲な量指定子を使用することで実現できます。
echo "The quick brown fox jumps in 2012 and 2013" \
| perl -pe 's/fox.*?([0-9]{4})//g'
余分なスペースも削除したほうがよいかもしれません。
答え2
使用したいと仮定するとのみsed で、数字の後の単語が何であるかを気にせずに、一致の終わりを最初の数字のグループにしたい場合は、次のようにします。
echo "2012年と2013年にクイックブラウンフォックスがジャンプ" \ | sed "s/fox[^0-9][^0-9]*[0-9][0-9]* //"
このパターンはfox
、 、1 つ以上の非数字[^0-9][^0-9]*
、1 つ以上の数字 を一致させることで機能します[0-9][0-9]*
。このパターンは、4 桁だけでなく、任意の桁数で機能します。正確に 4 桁の数字を一致させたい場合は、次のように変更します。
echo "2012年と2013年にクイックブラウンフォックスがジャンプ" \ | sed "s/fox[^0-9]*\([0-9]\{4\}\) //"
答え3
指定しませんでしたその通り要件は何ですか。複数のステップからなるプロセスが必要な場合があります。入力に出現しないことが分かっている文字列を選択します (例: ####
)。
echo 「素早い茶色のキツネは、2012 年と 2013 年に 42 匹の怠け者の犬を飛び越えました。」\ | sed \ -e "s/[0-9]\{4\}/&####/" \ -e "s/fox.*####//" \ -e "s/####//"
-e "s/[0-9]\{4\}/&####/"
(コマンドは####
読みやすくするために折り返されています。)最初65536
4桁の数字。(警告:これはに変更されます6553####6
。)は、と
-e "s/fox.*####//"
を含む行(つまり、少なくとも1つの4桁の数字を含む行)に影響し、 から までを削除します。fox
####
fox
最初4 桁の数字。
-e "s/####//"
は、もちろん、####
4 桁の数字は含まれているが は含まれていない行から残っている文字列をすべて削除しますfox
。
数字の後ろにスペースがある場合は、それも削除します。
echo 「素早い茶色のキツネは、2012 年と 2013 年に 42 匹の怠け者の犬を飛び越えました。」\ | sed \ -e "s/[0-9]\{4\}/&####/" \ -e "s/fox.*#### //" \ -e "s/fox.*####//" \ -e "s/####//"
g
警告:すべてのコマンドに を追加できますs
が、それでも を使用しているため.*
、これが問題の原因であり、処理されません。
One fox jumps in 2012 and 2013, another fox will jump in 2014 and 2015.
おそらくあなたが望む方法で。そしてもちろん、あなたはしないg
追加したいのは、その後に"s/[0-9]\{4\}/&####/"
注入するためです####
毎4桁の数字で、全体のポイントが無効になります。すると、(元のコマンドから不要な文字を取り除いた)"s/fox.*####//"
のとまったく同じように動作します。つまり、次のように変更されます。"s/fox.*[0-9]\{4\}//"
クイックブラウンフォックスは2012年と2013年にジャンプします。
に
クイック ブラウン フォックスは 2012#### と 2013#### にジャンプします。
そして
クイックブラウン。