Konvertieren Sie den Unterstrich in PascalCase, dh UpperCamelCase

28

Wenn ich eine Zeichenfolge habe, die so aussieht:

"this_is_the_string"

Innerhalb eines Bash-Skripts möchte ich es in PascalCase konvertieren, dh UpperCamelCase sieht folgendermaßen aus:

"ThisIsTheString"

Ich habe festgestellt, dass die Konvertierung in lowerCamelCase folgendermaßen erfolgen kann:

"this_is_the_string" | sed -r 's/([a-z]+)_([a-z])([a-z]+)/\1\U\2\L\3/'

Leider kenne ich mich mit Regexen nicht aus, um dies zu ändern.

user1135541
quelle
(1) Dies ist für diese Frage (und die bisher präsentierten Antworten) nicht wirklich von Bedeutung, aber, zu Ihrer Information, \U\2fügt den gefundenen Text aus der zweiten Gruppe ein, der in ALL CAPS konvertiert wurde. Vergleichen Sie mit \u\2, um den Text in Groß- und Kleinschreibung einzufügen. Dabei wird nur das erste Zeichen großgeschrieben. (2) Alle unten aufgeführten Beispiele übersetzen "this_is_a_string" in "ThisIsAString". Dies ist genau das, wonach Sie gefragt haben, aber es ist etwas schwer zu lesen. Möglicherweise möchten Sie Ihre Anforderungen für den Sonderfall eines Ein-Buchstaben-Wortes (Teilzeichenfolge) überarbeiten. … (Fortsetzung)
Scott
(Fortsetzung)… (3) Haben Sie nur einen solchen String pro Zeile? Und ist es immer der erste (oder der einzige ) Text in der Zeile? Wenn Sie eine Zeichenfolge haben, die nicht am Anfang der Zeile steht, wird sie durch die folgenden Antworten in lowerCamelCase konvertiert. Um das Problem zu beheben, nehmen Sie Janis 'Antwort und wechseln Sie (^|_)zu (\<|_).
Scott
1
inverse: stackoverflow.com/questions/28795479/…
Ciro Santilli

Antworten:

44
$ echo "this_is_the_string" | sed -r 's/(^|_)([a-z])/\U\2/g'            
ThisIsTheString

Ersetzen Sie das Muster
(^|_)am Anfang der Zeichenfolge oder nach einem Unterstrich - erste Gruppe
([a-z])einzelner Kleinbuchstabe - zweite Gruppe,
indem Sie die
\U\2zweite Gruppe
gglobal in Großbuchstaben setzen .

Janis
quelle
4
Hinweis: \Uist eine GNU-Erweiterung für POSIX.
Ciro Santilli
1
Nur eine Anmerkung, Sie sollten auch Zahlen erfassen sed -r 's/(^|[-_ ]+)([0-9a-z])/\U\2/g'. Also funktionieren auch Strings wie "this_is_2nd_string" .
1.
9

bashWenn Sie Ihre Zeichenfolge in einer Variablen gespeichert haben, können Sie sie seitdem auch nur in der Shell ausführen:

uscore="this_is_the_string_to_be_converted"
arr=(${uscore//_/ })
printf %s "${arr[@]^}"
ThisIsTheStringToBeConverted

${uscore//_/ }Ersetzt all _durch Leerzeichen, (....)teilt den String in ein Array, ${arr[@]^}konvertiert den ersten Buchstaben jedes Elements in Großbuchstaben und printf %s ..druckt dann alle Elemente nacheinander.
Sie können die Zeichenfolge mit dem Kamel in einer anderen Variablen speichern:

printf -v ccase %s "${arr[@]^}"

und später verwenden / wiederverwenden, zB:

printf %s\\n $ccase
ThisIsTheStringToBeConverted

Oder mit zsh:

uscore="this_is_the_string_to_be_converted"
arr=(${(s:_:)uscore})
printf %s "${(C)arr}"
ThisIsTheStringToBeConverted

(${(s:_:)uscore})Teilt den String _in ein Array auf, (C)schreibt den ersten Buchstaben jedes Elements in Großbuchstaben und printf %s ...druckt alle Elemente nacheinander aus.
Um ihn in einer anderen Variablen zu speichern, können Sie (j::)die Elemente verbinden:

ccase=${(j::)${(C)arr}}

und später verwenden / wiederverwenden:

printf %s\\n $ccase
ThisIsTheStringToBeConverted
don_crissti
quelle
8

Hier ist ein Perl-Weg:

$ echo "this_is_the_string" | perl -pe 's/(^|_)./uc($&)/ge;s/_//g'
ThisIsTheString

Es kann mit Strings beliebiger Länge umgehen:

$ echo "here_is_another_larger_string_with_more_parts" | 
    perl -pe 's/(^|_)./uc($&)/ge;s/_//g'
HereIsAnotherLargerStringWithMoreParts

Es stimmt mit jedem Zeichen ( .) überein , das nach dem Anfang der Zeichenfolge oder einem Unterstrich ( (^|_)) steht, und ersetzt es durch die Großbuchstabenversion von sich selbst ( uc($&)). Dies $&ist eine spezielle Variable, die alles enthält, was gerade abgeglichen wurde. Das eam Ende von s///geerlaubt die Verwendung von Ausdrücken ( uc()in diesem Fall die Funktion) innerhalb der Ersetzung und gbewirkt, dass alle Vorkommen in der Zeile ersetzt werden. Die zweite Ersetzung entfernt die Unterstriche.

terdon
quelle
Apropos Perl, es gibt auch ein Perl-Modul String :: CamelCase , das unterstrichenen Text "kamelisiert".
don_crissti
@don_crissti ooh, klingt perfekt dafür. Vielen Dank.
Terdon
Kürzere Perl:perl -pe 's/(^|_)([a-z])/uc($2)/ge'
Isaac
6

Es ist nicht erforderlich, die gesamte Zeichenfolge in einer Übereinstimmung mit regulären Ausdrücken darzustellen. Sed verfügt über den /gModifikator, mit dem Sie mehrere Übereinstimmungen durchgehen und jede ersetzen können:

echo "this_is_the_string" | sed 's/_\([a-z]\)/\U\1/g;s/^\([a-z]\)/\U\1/g'

Der erste reguläre Ausdruck ist _\([a-z]\)- jeder Buchstabe nach dem Unterstrich; der zweite stimmt mit dem ersten Buchstaben in einer Zeichenfolge überein.

myaut
quelle
3

Ich habe diese Antwort nur eingegeben, weil sie kürzer und einfacher ist als alle anderen bisher.

sed -re "s~(^|_)(.)~\U\2~g"

Es heißt: Großbuchstaben, das Zeichen nach einem _oder dem Start. Nichtbuchstaben werden nicht geändert, da sie keine Groß- und Kleinschreibung haben.

Strg-Alt-Delor
quelle
1
"Alles sollte so einfach wie möglich sein, aber nicht einfacher." - Albert Einstein. Dies entspricht nicht den anderen Antworten. Ihre Antwort wird "FOO_BAR" in "FOOBAR" konvertieren, während die anderen Antworten es in Ruhe lassen.
Scott
@scott Ah ja, daran habe ich nicht gedacht.
Strg-Alt-Delor
1
@Scott Ist das nicht das gewünschte Verhalten? Ich denke, dass es im Idealfall werden sollte, FooBaraber der Unterstrich sollte gemäß Anleitung entfernt werden. Da verstehe ich die Anleitung trotzdem.
Terdon
2
(Fortsetzung)… (3) Ich denke, es ist ziemlich klar, dass der Sinn der Frage darin besteht, eine Zeichenfolge so zu transformieren, dass durch Unterstriche ( _) angegebene Wortumbrüche stattdessen durch Übergänge in Groß- und Kleinschreibung angezeigt werden. Angesichts dessen ist "FOO_BAR" → "FOOBAR" eindeutig falsch (da die Wortumbruchinformationen verworfen werden), obwohl "FOO_BAR" → "FooBar" möglicherweise korrekt ist. (4) Ebenso scheint eine Abbildung, die Kollisionen verursacht, dem Sinn der Frage zu widersprechen. Ich glaube beispielsweise, dass eine Antwort, die "DO_SPORTS" und "DOS_PORTS" in dasselbe Ziel konvertiert, falsch ist.
Scott
1
(Fortsetzung wieder)… (5) Um keine Kollisionen zu verursachen, scheint es mir, dass “foo_bar” und “FOO_BAR” nicht dasselbe abbilden sollten, daher widerspreche ich “FOO_BAR” → “FooBar” . (6) Ich denke, das größere Problem sind Namespaces. Ich habe in Pascal nicht programmiert, seit Blaise am Leben war, aber in C / C ++ sind Bezeichner, die hauptsächlich in Kleinbuchstaben (einschließlich snake_case und CamelCase) geschrieben sind, im Allgemeinen die Domäne des Compilers, während Bezeichner in Großbuchstaben die sind Domäne des Vorprozessors. Aus diesem Grund wollte das OP meiner Meinung nach nicht, dass ALL_CAPS-Bezeichner berücksichtigt werden.
Scott
1

In Perl:

$ echo 'alert_beer_core_hemp' | perl -pe 's/(?:\b|_)(\p{Ll})/\u$1/g'
AlertBeerCoreHemp

Dies ist auch nicht möglich:

$ echo 'алерт_беер_коре_хемп' | perl -CIO -pe 's/(?:\b|_)(\p{Ll})/\u$1/g'
АлертБеерКореХемп
Mosvy
quelle
0

Ich habe es so gemacht:

echo "this_is_the_string" | sed -r 's/(\<|_)([[:alnum:]])/\U\2/g'

und habe folgendes Ergebnis:

ThisIsTheString
Fábio Roberto Teodoro
quelle