awk veya sed - küçük harf / büyük harf


13

Bazı dizgide yalnızca bir karakteri büyük / küçük harfle yazmanın bir yolu var mı?

Giriş Örneği:

syslog_apr_24_30
syslog_mar_01_17

Istenilen çıktı:

syslog_Apr_24_30
syslog_Mar_01_17

Lütfen ayın başındaki büyük harfe dikkat edin.

Denedim awkama çalıştıracak kadar iyi değilim.

Yanıtlar:


18

Sen kullanabilirsiniz \umektup büyük harfe GNU içinde sed:

sed -e 's/_\(.\)/_\u\1/' input

Perl aynısını yapar:

perl -pe 's/_(.)/_\u$1/' input

\l tam tersini yapar.


8
Daha basit bir dokunuş:sed 's/_./\U&/'
Glenlen Jackman

4

awk:

echo "syslog_apr_24_30" | 
  awk -F'_' '{print $1"_"toupper(substr($2,1,1)) substr($2,2)  "_"$3"_"$4}'

3

Awk alt dizeleri ve toupper ile sürüm

awk 'BEGIN{ FS=OFS="_"} {
        cap=toupper(substr($2,1,1));
        lower=substr($2,2,3);
        $2 = cap lower; print 
}' list.txt 

Örnek çalışma:

$ awk 'BEGIN{ FS=OFS="_"} { 
    cap=toupper(substr($2,1,1));
    lower=substr($2,2,3);$2 = cap lower; print 
}' list.txt               
syslog_Apr_24_30
syslog_Mar_01_17

3

Kullanma awk:

awk -F_ '{
    printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"
}' foo

veya

awk -F_ '{
    for(i=1;i<=NF;i++) {
        if(i==2){
            printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)
        } 
        else {printf "%s",$i} 
        if(i<NF) {printf "%s","_"}
    } printf "%s","\n"}' foo

Misal

% cat foo
syslog_apr_24_30
syslog_mar_01_17

% awk -F_ '{for(i=1;i<=NF;i++) {if(i==2){printf "%s",toupper(substr($i,1,1))substr($i,2,length($i)-1)} else {printf "%s",$i} if(i<NF) {printf "%s","_"}} printf "%s","\n"}' foo
syslog_Apr_24_30
syslog_Mar_01_17

% awk -F_ '{printf "%s_%s_%s_%s",$1,toupper(substr($2,1,1))substr($2,2,2),$3,$4"\n"}' foo 
syslog_Apr_24_30
syslog_Mar_01_17

3

İşte bir Perl yaklaşımı:

$ perl -pe 's/_./uc($&)/e' file
syslog_Apr_24_30
syslog_Mar_01_17

-pTarafından verilen komut uygulandıktan sonra baskılı her satırı neden olur -e. İkame ilk örneğinin _ve onu izleyen karakterin kendisiyle ( $&eşleştirilen her şeydir ) üst kasanın ( uc()) eyerini alır s///e. İfadeleri değerlendirmek için ikame operatörünün ( ) sonunda gereklidir.


2

Başka bir perl:

perl -F_ -anle '$F[1] = ucfirst $F[1];print join "_", @F'

1

Pure Bash 4.x, üstlenmek istediğiniz parçayı seçmek için bir normal ifade ve o ^^bölümdeki üstteki işleci kullanarak. Tüm dizeyi yeniden oluşturmak için ön ve arkada (. * İle eşleştirilir) birleştirme:

foo=syslog_apr_24_30
if [[ $foo =~ (.*)(_[a-z])(.*) ]]; then
    foo=${BASH_REMATCH[1]}${BASH_REMATCH[2]^^}${BASH_REMATCH[3]}
fi

Tüm alıntı kurallarını hatırlamıyorsanız, normal ifade hariç her şeyi alıntılamak güvenlidir (bu da =~gerçek bir dize eşleşmesi yapar).

İlk büyük ^harf operatörü yalnızca bir değişkenin (veya dizi öğesinin) başında çalışır. Ve perl'in lvalue olarak adlandırdığı (atamak / değiştirmek için atayabileceğiniz) herhangi bir alt dize genişletmesi yok gibi görünüyor. İlk / yukarı küçük harf işleçleri, karakter başına esasına göre bir desen alabilir, ancak atlamaya yardımcı olmaz syslog_, çünkü "syslog" da karakterlerle başlayan ay adları vardır.

Her neyse, bu daha hızlı olabilir foo="$(echo "$foo" | sed 's/_./\U&/')"(kabul edilen cevaba yorum olarak Glenn Jackman tarafından gönderildi).

Bash, sed veya awk perl'den çok daha hızlı olacaktır. Bir kabuk betiğinde birden çok perl tek katmanı bulmaya başlarsanız, her şeyi perl'e yazmanız gerekir.


0

Ay her zaman ilk "_" (alt çizgiyi) izliyorsa, bunu kullanın (diğer yanıtlarda gösterildiği gibi):

sed -e 's/_\(.\)/_\u\1/'

Ayın öncesinden önce başka alt çizgiler varsa, yukarıdaki çalışmaz.

Ay her zaman 8. karakterle başlıyorsa, bunu kullanın:

sed -e 's/^\(.\{7\}\)\(.\)/\1\u\2/'
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.