awk o sed in minuscolo / maiuscolo solo un carattere nella stringa?


13

C'è un modo come maiuscolo / minuscolo solo un carattere in una stringa?

Esempio di input:

syslog_apr_24_30
syslog_mar_01_17

Uscita desiderata:

syslog_Apr_24_30
syslog_Mar_01_17

Nota per favore l'inizio maiuscolo del mese.

Ho provato awkma non sono abbastanza bravo per farlo funzionare.

Risposte:


18

Puoi usare \uGNU sed per scrivere una lettera maiuscola:

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

Perl fa lo stesso:

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

\l fa il contrario.


8
Un tocco più semplice:sed 's/_./\U&/'
glenn jackman,

4

awk:

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

3

Awk versione con sottostringhe e toupper

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

Esecuzione di esempio:

$ 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

Utilizzando awk:

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

o

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

Esempio

% 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

Ecco un approccio Perl:

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

Questo -pfa sì che ogni riga venga stampata dopo aver applicato lo script fornito da -e. La sostituzione sostituisce la prima istanza di _e il carattere che la segue con se stessi ( $&è qualunque cosa sia stata abbinata) maiuscolo ( uc()), eal fine dell'operatore di sostituzione ( s///e) è necessario per valutare le espressioni.


2

Un altro perl:

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

1

Pure Bash 4.x, usando un regex per selezionare la parte che si desidera upcase e l' ^^operatore upcase su quella parte. Tacking sul davanti e sul retro (abbinato a. *) Per ricreare l'intera stringa:

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

Se non ricordi tutte le regole di quotazione, è sicuro citare tutto tranne la regex (che farebbe =~una corrispondenza stringa letterale).

L' ^operatore upcase-first funziona solo all'inizio di una variabile (o elemento array). E non sembra esserci alcuna espansione di sottostringa che ti dia quello che perl chiamerebbe un valore (che puoi assegnare / modificare). Gli operatori up / downcase-first possono prendere uno schema corrispondente per carattere, ma ciò non aiuta a saltare syslog_, perché ci sono nomi di mese che iniziano con caratteri in "syslog".

Comunque, questo potrebbe essere più veloce di foo="$(echo "$foo" | sed 's/_./\U&/')"(pubblicato come commento alla risposta accettata, da Glenn Jackman).

Bash, sed o awk saranno MOLTE volte più veloci di perl. Se inizi a trovare più per-line perl utili in uno script di shell, dovresti semplicemente scrivere tutto in perl.


0

Se il mese segue sempre il primo "_" (trattino basso), usa questo (come mostrato nelle altre risposte):

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

Se potrebbero esserci altri caratteri di sottolineatura prima di quello che precede il mese, allora quanto sopra non funzionerà.

Se il mese inizia sempre con l'ottavo carattere, utilizza questo:

sed -e 's/^\(.\{7\}\)\(.\)/\1\u\2/'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.