いくつかの調査を行いましたが、文字列を「。」で区切ることができます。しかし、置換したいのは3番目の「。」だけです。バージョン番号は実際には可変なので、どのように置換/分割できますか?
version: 1.8.0.110
しかし、私が欲しいのは次のような出力です:
version: 1.8.0-110
使用されたsed
例:
$ echo 'version: 1.8.0.110' | sed 's/\./-/3'
version: 1.8.0-110
説明:
sed s/search/replace/x
は文字列を検索し、2番目を置き換えます。 x
は置換するオカレンスを決定します-ここでは3番目です。多くの場合、g
は、すべての出現を意味するx
に使用されます。
ここでは、ドット.
を置き換えたいと思いますが、これはsed
がsearch
用語で期待する正規表現の特殊文字です。したがって、.
を\.
にバックスラッシュして、リテラル.
を指定します。
sed
(ここでは円記号\
)の引数に特殊文字を使用しているため、引数全体を単一引用符''
で囲む必要があります。多くの人は、ここでは常に引用符を使用して、シェルに特別な文字(spaceなど)を使用するときに問題が発生しないようにしています。
特にlastピリオドをダッシュに置き換えたいように見えるので、これを行うのに外部プログラムは必要ありません。 Bashは文字列操作自体を処理できます。
あなたが持っていると思います
vers='version: 1.8.0.110'
答えは簡単です:
$ echo ${vers%.*}-${vers##*.}
1.8.0-110
%は、一致する右側の最も短い文字列を削除することを意味します。 ##は、一致する左側の最も長い文字列を削除することを意味します。
上記で推定した最後の期間ではなく、実際に3番目の期間を置き換える場合は、bashで少しトリッキーになりますが、それでも可能です。たとえば、vers='version: 1.8.0.110.hut.hut.hut.hike!'
、3番目のピリオド以降をすべて検索し、それを使用して文字列を切り捨てることができます。
$ end=${vers#*.*.*.}
$ start=${vers%$end}
$ echo ${start%.}-$end
version: 1.8.0-110.hut.hut.hut.hike!
これは質問に対してはやり過ぎですが、文字列をコンポーネントに分割して配列にロードすると便利な場合があります。
IFS=. read -a foo <<<'version: 1.8.0.110.hut.hut.hut.hike!'
配列$foo
何をいつ印刷するかを選択します。例えば、
echo -n $foo
for ((i=1; i<${foo[@]}; i++)); do
[[ i -eq 3 ]] && echo -n - || echo -n .
echo -n ${foo[i]};
done
echo
この場合、3番目は最後の1つでもあります。常に最後の_.
_を変更する必要があると安全に想定できる場合は、次のようにすることができます。
_$ echo 'version: 1.8.0.110' | sed 's/\.\([^.]*\)$/-\1/'
version: 1.8.0-110
_
または、sed
が_-E
_をサポートしている場合(ほとんどの場合)は次のとおりです。
_$ echo 'version: 1.8.0.110' | sed -E 's/\.([^.]*)$/-\1/'
version: 1.8.0-110
_
これは、_.
_を検索し、その後、行の終わり(_.
_)まで0以上の非_[^.]
_文字(_$
_)を検索します。 _[^.]*
_は括弧(\( \)
)内にあるため、「キャプチャー」され、置換演算子の右側で_\1
_として参照できます。したがって、これは_.
_およびその後ろのnon _-.
_文字を_-
_およびそれらの文字に置き換えます。
最後ではなく3番目にする必要がある場合、 @ Ned64はすでに最も単純なアプローチを提供しています ですが、代わりに次のようにすることもできます。
_$ echo 'version: 1.8.0.110' | Perl -pe 's/(([^.]+\.){2}[^.]+)\./$1-/'
version: 1.8.0-110
_