いくつかの調査を行った結果、文字列を「.」に分割できますが、置き換えたいのは3番目の「.」で、バージョン番号は実際には可変であるため、置き換え/分割をどのように実行しますか?
version: 1.8.0.110
しかし、私が望むものは次のように出力されます。
version: 1.8.0-110
答え1
たとえば、次のようになりますsed
。
$ echo 'version: 1.8.0.110' | sed 's/\./-/3'
version: 1.8.0-110
説明する:
sed s/search/replace/x
文字列を検索して別の文字列に置き換えます。x
交換するイベントを識別します。 3番目のイベントは次のとおりです。一般的に発生するすべての状況を指すためg
に使用されます。x
ここでは点を置き換えようとしますが、これは正規表現の用語に必要な特殊文字です.
。したがって、リテラルを指定するためにバックスラッシュを使用します。sed
search
.
\.
.
パラメータに特殊文字sed
(ここではバックスラッシュ)を使用しているため、パラメータ\
全体を一重引用符で囲む必要があります''
。多くの人は、スペースなどのシェル固有の文字を使用する問題を避けるために、常にここで引用符を使用しています。
答え2
バッシュを使って
特に交換したいと思うので、これを行うために外部プログラムは必要ありません。最後ダッシュのあるピリオドです。 Bashはデフォルトで文字列操作を処理できます。
あなたが持っていると仮定
vers='version: 1.8.0.110'
答えは簡単です。
$ echo ${vers%.*}-${vers##*.}
1.8.0-110
% は右から一致する最短文字列を削除することを意味します。 ##は、左から一致する最も長い文字列を削除することを意味します。
3サイクルを超えるとどうなりますか?
上記のように、最後の期間の代わりに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を使用して文字列をbash配列に分割する
この問題については多少過度の作業ですが、時には文字列をコンポーネントに分割して配列にロードするのが便利な場合があります。
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
この場合、3番目で最後です。常に最後の項目を変更する必要があると安全に想定できる場合は、.
次のようにできます。
$ 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
行末()までを検索し、.
ゼロ個以上の文字以外の.
文字()を探します。括弧()で囲まれているため、「キャプチャ」され、置換演算子の右側で参照できます。したがって、次の文字と非文字はaとその文字に置き換えられます。[^.]
$
[^.]*
\( \)
\1
.
-.
-
今回が最後ではなく3回目でなければならない場合@Ned64が最も簡単な方法を提示しました。しかし、代わりに、次のことができます。
$ echo 'version: 1.8.0.110' | perl -pe 's/(([^.]+\.){2}[^.]+)\./$1-/'
version: 1.8.0-110