Alt çizgiyi PascalCase'e, yani UpperCamelCase'e dönüştürün


28

Bu gibi görünen bir dize varsa:

"this_is_the_string"

Bir bash betiğinin içinde, bunu PascalCase'e, yani UpperCamelCase'e şöyle dönüştürmek istiyorum:

"ThisIsTheString"

LowerCamelCase'e dönüştürmenin şu şekilde yapılabileceğini öğrendim:

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

Maalesef bunu değiştirmek için regex'lere yeterince aşina değilim.


(1) Bu soru (ve şu ana kadar verilen cevaplar) söz konusu olduğunda, bu gerçekten önemli değil, ancak FYI, \U\2bulunan metni TÜM CAPS'a dönüştürülen ikinci gruptan ekler. İle karşılaştır \u\2sadece ilk harfi büyük olan, Cümle durumda metin ekler, hangi. (2) Aşağıda verilen tüm örnekler, “this_is_a_string” i “ThisIsAString” e çevirecektir - bu sizin istediğiniz şeydi fakat okuması biraz zor. Tek harfli bir sözcüğün (alt dize) özel durumu için gereksinimlerinizi gözden geçirmek isteyebilirsiniz. … (Devamı)
Scott

(Devam ediyor)… (3) Satır başına yalnızca bir tane dizginiz var mı? Ve her zaman satırdaki ilk (veya tek ) metin midir? Satırın başında olmayan bir dizginiz varsa, aşağıdaki cevaplar onu altCamelCase'e dönüştürecektir. Düzeltme için, Janis cevabı ve değişimi almak (^|_)için (\<|_).
Scott,

Yanıtlar:


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

Yedek desen
(^|_)dize başlangıcında veya bir alt çizgi sonra - Birinci grup
([a-z])tek bir küçük harftir - İkinci grup
tarafından
\U\2ikinci grup uppercasing
gglobal.


4
Not: \U POSIX'e bir GNU uzantısıdır.
Ciro Santilli,

1
Sadece bir not, sayıları da almalısın sed -r 's/(^|[-_ ]+)([0-9a-z])/\U\2/g'. Yani "this_is_2nd_string" gibi dizeler de işe yarıyor.
pinkeen

9

Kullandığınızdan beri bash, dizginizi bir değişkende sakladıysanız, sadece kabuk olarak da yapabilirsiniz:

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

${uscore//_/ }hepsini _boşlukla değiştirir , (....)diziyi diziye böler, ${arr[@]^}her öğenin ilk harfini büyük harfe dönüştürür ve ardından printf %s ..tüm öğeleri birbiri ardına yazdırır.
Deve kuşu dizesini başka bir değişkende saklayabilirsiniz:

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

ve daha sonra kullanın / yeniden kullanın, örneğin:

printf %s\\n $ccase
ThisIsTheStringToBeConverted

Veya zsh:

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

(${(s:_:)uscore}) dize böler _diziyi bir diziye(C) her bir öğenin ilk harfini büyük harf yapar ve printf %s ...tüm öğeleri birbiri ardına basar . Öğeleri birleştirmek için
kullanabileceğiniz başka bir değişkende saklamak için (j::):

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

ve daha sonra kullanın / yeniden kullanın:

printf %s\\n $ccase
ThisIsTheStringToBeConverted

8

İşte Perl yolu:

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

İsteğe bağlı uzunluktaki dizelerle başa çıkabilir:

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

.Dizenin başlangıcından sonra gelen herhangi bir karakterle ( ) veya bir alt çizgi ( (^|_)) ile eşleşecek ve onu büyük harfli sürümüyle ( uc($&)) değiştirecektir. Bu $&sadece neyin eşleştirildiğini içeren özel bir değişkendir. eSonunda s///geifadelerin kullanılmasını (verir uc()ikamesi içinde bu durumda fonksiyonu) ve gbunu değiştirmek yapar tüm çizgi oluşumlarını. İkinci ikame alt çizgileri kaldırır.


Perl'den bahsetmişken, altı çizili metni "kamelize eden" bir perl modülü de vardır String: CamelCase .
don_crissti

@ don_crissti ooh, bunun için mükemmel sesler. Teşekkürler.
terdon

Kısa Perl:perl -pe 's/(^|_)([a-z])/uc($2)/ge'
Isaac

6

Dizenin tamamını düzenli ifade eşleşmesinde göstermek gerekli değildir - sed, /gbirden fazla eşleşmeden geçip her birini değiştirmenize olanak sağlayan değiştiriciye sahiptir:

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

İlk regex _\([a-z]\)- alt çizgiden sonraki her harf; ikincisi bir dizedeki ilk harfle eşleşir.


3

Ben sadece bu cevaba cevap verdim çünkü şu ana kadar diğerlerinden daha kısa ve basit.

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

Diyor ki: büyük, a _veya sonraki karakter . Harf olmadıkça harfler olmayan harfler değişmeyecektir.


1
"Her şey mümkün olduğunca basit yapılmalı, ancak daha basit olmamalı." - Albert Einstein. Bu diğer cevaplara eşdeğer değildir; cevabınız "FOO_BAR" ifadesini "FOOBAR" olarak değiştirirken, diğer cevaplar onu yalnız bırakacaktır.
Scott,

@scott Ah evet, bunu düşünmedim.
ctrl-alt-delor 14:15

1
@Scott İstenilen davranış bu değil mi? Bence bu ideal olmalı, FooBarancak alt çizgi yönergelere göre kaldırılmalıdır. Zaten talimatları anladığım gibi.
terdon

2
(Devam ediyor)… (3) Sorunun ruhunun bir dizgeyi dönüştürmek olduğunu, böylece alt çizgi ( _) ile belirtilen sözcük sonlarının bunun yerine büyük / küçük harf geçişleriyle gösterildiğini açıkça düşünüyorum . “FOO_BAR” → “FOOBAR” açıkça yanlış olduğu için (kelime sonu bilgisini atarken), “FOO_BAR” → “FooBar” doğru olmasına rağmen. (4) Benzer şekilde, çarpışmalara neden olan bir haritalamanın sorunun ruhuna aykırı olduğu görülmektedir. Örneğin, “DO_SPORTS” ve “DOS_PORTS” u aynı hedefe dönüştüren bir cevabın yanlış olduğuna inanıyorum.
Scott,

1
(Tekrar devam)… (5) Çarpışmaya neden olmama ruhu ile bana “foo_bar” ve “FOO_BAR” aynı şeyle eşleşmemeliydi, bu yüzden “FOO_BAR” → “FooBar” a itiraz ediyorum . (6) En büyük sorunun isim alanları olduğunu düşünüyorum. Blaise hayatta olduğundan beri Pascal programlamamıştım, ancak C / C ++ 'da, konvansiyonel olarak, öncelikle küçük harf olan tanımlayıcılar (snake_case ve CamelCase dahil) genellikle derleyicinin alanı, büyük harf tanımlayıcıları ise ön işlemcinin alanı. Bu yüzden OP'nin ALL_CAPS tanımlayıcılarının değerlendirilmesini istemediğini düşünüyorum.
Scott,

1

Perl'de:

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

Bu aynı zamanda i18n-mümkün:

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

0

Bu şekilde yaptım:

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

ve bu sonucu aldım:

ThisIsTheString
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.