awk oder sed, um nur ein Zeichen in der Zeichenkette in Klein- / Großschreibung zu schreiben?

13

Gibt es eine Möglichkeit, nur ein Zeichen in einer Zeichenfolge in Groß- / Kleinschreibung zu schreiben?

Eingabebeispiel:

syslog_apr_24_30
syslog_mar_01_17

Gewünschte Ausgabe:

syslog_Apr_24_30
syslog_Mar_01_17

Beachten Sie bitte den Großbuchstaben Anfang des Monats.

Ich habe es versucht, awkaber ich bin nicht gut genug, um es zum Laufen zu bringen.

molni
quelle

Antworten:

18

Sie können \uin GNU sed verwenden, um einen Buchstaben in Großbuchstaben zu schreiben:

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

Perl macht dasselbe:

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

\l macht das Gegenteil.

Choroba
quelle
8
Ein Hauch einfacher: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}'
Michael Durrant
quelle
3

Awk Version mit Teilstrings und Topper

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

Probelauf:

$ 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
Sergiy Kolodyazhnyy
quelle
3

Verwenden von awk:

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

oder

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

Beispiel

% 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
AB
quelle
3

Hier ist ein Perl-Ansatz:

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

Das -pbewirkt, dass jede Zeile gedruckt wird, nachdem das von angegebene Skript angewendet wurde -e. Die Ersetzung ersetzt die erste Instanz von _und das darauf folgende Zeichen durch sich selbst ( $&was auch immer gefunden wurde). Großbuchstaben ( uc()). Der eOperator ( s///e) am Ende der Ersetzung wird benötigt, um Ausdrücke auszuwerten.

terdon
quelle
2

Ein anderer perl:

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

Pure Bash 4.x verwendet einen regulären Ausdruck, um den Teil, den Sie in Großbuchstaben ^^schreiben möchten, und den Operator in Großbuchstaben für diesen Teil auszuwählen. Heften an Vorder- und Rückseite (mit. *), Um die gesamte Zeichenfolge neu zu erstellen:

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

Wenn Sie sich nicht an alle Anführungsregeln erinnern, ist es sicher, alles mit Ausnahme des regulären Ausdrucks zu zitieren =~ einer wörtlichen Zeichenfolgenübereinstimmung führen .

Der ^Operator upcase-first steht nur am Anfang einer Variablen (oder eines Array-Elements). Und es scheint keine Teilstringerweiterung zu geben, die Ihnen einen Wert gibt, den Perl als l-Wert bezeichnen würde (den Sie zuweisen / ändern können). Die Operatoren für Groß- und Kleinschreibung können ein Muster verwenden, das auf Zeichenbasis abgeglichen wird, das Überspringen hilft jedoch nichtsyslog_ , da es Monatsnamen gibt, die mit Zeichen in "syslog" beginnen.

Auf jeden Fall könnte dies schneller sein als foo="$(echo "$foo" | sed 's/_./\U&/')" (gepostet als Kommentar zur akzeptierten Antwort von Glenn Jackman).

Bash, sed oder awk sind VIELE Male schneller als Perl. Wenn Sie anfangen, in einem Shell-Skript mehrere Perl-Einzeiler zu finden, sollten Sie das Ganze einfach in Perl schreiben.

Peter Cordes
quelle
0

Wenn der Monat immer auf das erste "_" (Unterstrich) folgt, verwenden Sie dies (wie in anderen Antworten gezeigt):

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

Wenn vor dem Monat andere Unterstriche angezeigt werden, funktioniert das oben Genannte nicht.

Wenn der Monat immer mit dem achten Zeichen beginnt, verwenden Sie Folgendes:

sed -e 's/^\(.\{7\}\)\(.\)/\1\u\2/'
Kevin Fegan
quelle