So teilen Sie eine Zeichenfolge durch das dritte (Punkt-) Trennzeichen

7

Ich habe ein paar Nachforschungen angestellt, ich kann die Zeichenfolge durch '.' Aber das einzige, was ich ersetzen möchte, ist das dritte '.', und die Versionsnummer ist tatsächlich variabel. Wie kann ich das Ersetzen / Teilen durchführen?

version: 1.8.0.110

aber was ich will, ist die Ausgabe wie folgt:

version: 1.8.0-110
Tiger
quelle

Antworten:

33

Verwendet sedzum Beispiel:

$ echo 'version: 1.8.0.110' | sed 's/\./-/3'
version: 1.8.0-110

Erläuterung:

sed s/search/replace/xsucht nach einer Zeichenfolge und ersetzt die zweite. xbestimmt, welches Vorkommen ersetzt werden soll - hier das 3 .. Wird oft gverwendet x, um alle Vorkommen zu bezeichnen.

Hier möchten wir den Punkt ersetzen, .aber dies ist ein Sonderzeichen im regulären Ausdruck, der sedim searchBegriff erwartet wird . Daher setzen wir das Backslashify .auf \., um ein Literal anzugeben ..

Da wir im Argument für sed(hier den Backslash \) Sonderzeichen verwenden , müssen wir das gesamte Argument in einfache Anführungszeichen setzen ''. Viele Leute verwenden hier immer Anführungszeichen, um nicht auf Probleme zu stoßen, wenn Zeichen verwendet werden, die für die Shell besonders sein könnten (z. B. Leerzeichen ).

Ned64
quelle
3

Verwenden Sie Bash

Sie benötigen dazu kein externes Programm, zumal Sie anscheinend den letzten Punkt durch einen Bindestrich ersetzen möchten . Bash kann String-Manipulationen selbst durchführen.

Vorausgesetzt du hast

vers='version: 1.8.0.110'

Die Antwort lautet einfach:

$ echo ${vers%.*}-${vers##*.}
1.8.0-110

% Bedeutet, dass die kürzeste übereinstimmende Zeichenfolge rechts gelöscht wird. Das ## bedeutet, dass die längste übereinstimmende Zeichenfolge links gelöscht wird.

Was ist, wenn es mehr als drei Perioden gibt?

Wenn Sie tatsächlich die dritte Periode ersetzen möchten, nicht die letzte Periode, wie ich oben angenommen habe, wird es in Bash etwas schwieriger, aber es ist immer noch möglich. Wenn Sie beispielsweise vers='version: 1.8.0.110.hut.hut.hut.hike!'nach der dritten Periode alles finden und damit die Zeichenfolge abschneiden können:

$ end=${vers#*.*.*.}
$ start=${vers%$end}
$ echo ${start%.}-$end
version: 1.8.0-110.hut.hut.hut.hike!

Eine andere Möglichkeit: Verwenden Sie IFS, um Zeichenfolgen in ein Bash-Array aufzuteilen

Während dies für die Frage übertrieben ist, ist es manchmal nützlich, eine Zeichenfolge in Komponenten aufzuteilen und diese in ein Array zu laden.

IFS=. read -a foo <<<'version: 1.8.0.110.hut.hut.hut.hike!'

Sie können das Array durchlaufen $foound auswählen, was wann gedruckt werden soll. Zum Beispiel,

echo -n $foo
for ((i=1; i<${foo[@]}; i++)); do 
  [[ i -eq 3 ]] && echo -n - || echo -n .
  echo -n ${foo[i]};
done
echo
hackerb9
quelle
2

In diesem Fall ist der dritte auch der letzte. Wenn Sie davon ausgehen können, dass Sie immer den letzten ändern müssen ., können Sie Folgendes tun:

$ echo 'version: 1.8.0.110' | sed 's/\.\([^.]*\)$/-\1/'
version: 1.8.0-110

oder, wenn Ihre sedUnterstützung -E(die meisten tun) mit:

$ echo 'version: 1.8.0.110' | sed -E 's/\.([^.]*)$/-\1/'
version: 1.8.0-110

Das sucht nach a .und dann nach 0 oder mehr Nichtzeichen .( [^.]) bis zum Ende der Zeile ( $). Da das [^.]*in Klammern ( \( \)) steht, wird es "erfasst" und kann als \1auf der rechten Seite des Ersatzoperators bezeichnet werden. Dies ersetzt also die .und die Nicht- -.Zeichen danach durch ein -und diese Zeichen.


Wenn es der dritte und nicht der letzte sein muss, hat @ Ned64 bereits den einfachsten Ansatz angegeben , aber als Alternative können Sie Folgendes tun:

$ echo 'version: 1.8.0.110' | perl -pe 's/(([^.]+\.){2}[^.]+)\./$1-/'
version: 1.8.0-110
terdon
quelle