Entfernen Sie mit sed Leerzeichen nach einzelnen Großbuchstaben

Entfernen Sie mit sed Leerzeichen nach einzelnen Großbuchstaben

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 Settingsmuss 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 ChadwickundA B C D'Souza

Texte wie A B cdeund A B CDEwerden nicht verändert.

Es verwendet zwei temporäre Nullzeichen, \x00um Änderungen (pro Name) beim Fortschreiten durch eine Zeile zu markieren und Leerzeichen zu entfernen.

:Nund :SsindVerzweigung nachBeschriftungen (jeder Name ist ausreichend)
tund bsind Verzweigungsanweisungen.
tVerzweigt nach einem erfolgreichen Ersetzen im vorherigen s/../../Befehl.
bVerzweigt 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 perles 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, sedda 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. \nist 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!

verwandte Informationen