
Ich schreibe ein Bash-Skript, um automatisch einige andere Dateien zu generieren, und ich muss einige Zeichenfolgen auf eine bestimmte Weise formatieren. Das letzte Problem, das ich habe, ist die Formatierung einer Zeichenfolge, die einzelne Großbuchstaben und ein Wort enthält, das mit einem Großbuchstaben beginnt. Beispiel:
O S D Settings
muss werdenOSD Settings
Ich habe einen sed-Befehl, der das erste Leerzeichen entfernt, aber auch das „D“ (also O S D Settings
-> OS Settings
) löscht. Dieser Befehl lautet:
O S D Settings | sed 's/ \([A-Z]\)* \(A-Za-z]*\)/\1/g'
Weiß jemand, wie man die Leerzeichen zwischen einzelnen Großbuchstaben löschen kann, ohne dass Buchstaben verloren gehen?
Antwort1
Dies kümmert sich um Namen wie A B Chadwick
undA B C D'Souza
Texte wie A B cde
und A B CDE
werden nicht verändert.
Es verwendet zwei temporäre Nullzeichen, \x00
um Änderungen (pro Name) beim Fortschreiten durch eine Zeile zu markieren und Leerzeichen zu entfernen.
:N
und :S
sindVerzweigung nachBeschriftungen (jeder Name ist ausreichend)
t
und b
sind Verzweigungsanweisungen.
t
Verzweigt nach einem erfolgreichen Ersetzen im vorherigen s/../../
Befehl.
b
Verzweigt bedingungslos.
sed -r ":N # loop per name
/(\<[A-Z]\> )+[A-Z][a-z']/{ # line needs action
s/((\<[A-Z]\> )+)([A-Z][a-z'])/\x00\1\x00\3/ # add \x00 markers
:S # loop per space
s/(\x00[A-Z]+) (\<[A-Z]\>)/\1\2/ # delete a space
t S # any more spaces?
b N # any more names?
}; s/\x00//g" # remove \x00
Antwort2
Es ist schwierig mit sed
, aber wenn perl
es in Ordnung ist, können Sie es so machen
echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
Dies ist schwierig, sed
da keine Vorausschau-Behauptungen unterstützt werden.
Prüfungen:
echo O S D | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D. | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo One O DDE T. S Asdf Q R Tee | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D\ | perl -p -e 's/([A-Z]) (?=.([^\w]|$))/$1/g'
Wenn Sie eine schlampige Lösung mit wollen sed
, versuchen Sie
echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
Das funktioniert für Ihr Beispiel, wird aber in anderen Fällen fehlschlagen.
Prüfungen:
echo O S D | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D. | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo One O DDE T. S Asdf Q R Tee | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D\ | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
Antwort3
Das könnte für Sie funktionieren:
echo "O S D Settings and B T W and A B C D'Souza too F Y I" |
sed ':a;s/\(\<[[:upper:]]\>\) \(\<[[:upper:]]\>\([^'\'']\|$\)\)/\1\n\2/g;ta;s/\n//g'
OSD Settings and BTW and ABC D'Souza too FYI
Erläuterung:
Verwenden Sie ein Zeichen, das in der ursprünglichen Zeichenfolge nicht vorhanden ist, um die zu löschenden Leerzeichen zu ersetzen, und löschen Sie dann das ausgewählte Zeichen in der gesamten Zeichenfolge. \n
ist ein guter Kandidat, da es normalerweise nicht vorhanden sein kann, weil es von sed als Zeilentrennzeichen verwendet wird.
Antwort4
Letztendlich habe ich einfach sed mit Pipes verwendet, um eine für mich leicht verständliche Anweisung zu erhalten:
echo O S D Settings | sed 's/\([A-Z][^ ]\)/_\1/g' | sed 's/ //g' | sed 's/_/ /g'
Das ersetzt lediglich die Leerzeichen, die ich nicht haben möchte, durch den Unterstrich und löscht sie dann. Danke für alle Antworten!