2012-08-03 1 views
15

Ich habe drei Arten von Zeichenfolgen, die ich in einem Bash-Skript groß schreiben möchte. Ich dachte sed/awk wäre meine beste Wette, aber ich bin mir nicht sicher. Was ist der beste Weg, um die folgenden Anforderungen zu erfüllen?sed/awk Großschreibung Strings

1.) einzelnes Wort z.B. taco -> Taco

2.) mehrere Wörter getrennt durch Bindestriche z.B. my-fish-tacos -> My-Fish-Tacos

3.) mehrere Wörter getrennt durch Unterstriche z.B. my_fish_tacos -> My_Fish_Tacos

Antwort

26

Es gibt keine Notwendigkeit Capture-Gruppen zu verwenden (obwohl & eine Eins in einer Art und Weise ist):

echo "taco my-fish-tacos my_fish_tacos" | sed 's/[^ _-]*/\u&/g' 

Der Ausgang:

Taco My-Fish-Tacos My_Fish_Tacos 

Die Escape-Kleinbuchstabe "u" setzt das nächste Zeichen in der übereinstimmenden Teilzeichenfolge groß.

+0

Wie würde ich das ändern, um Wörter zu behandeln, die All-Caps sind? Zum Beispiel my-FISH-TACOS sollte My-Fish-Tacos ausgeben. – GregB

+4

@GregB: Sagen Sie es Kleinbuchstaben alle Zeichen dann Großbuchstaben das nächste: 'sed 's/[^ _-] */\ L \ u &/g'' –

+2

Hinweis: Dies ist eine GNU sed-Erweiterung.BSD sed Benutzer (einschließlich OS X) können dies nicht tun. – Jashank

6

Versuchen Sie Folgendes:

sed 's/\([a-z]\)\([a-z]*\)/\U\1\L\2/g' 

Es funktioniert für mich mit GNU sed, aber ich glaube nicht, BSD sed \U und \L unterstützt.

6

Mit awk:

echo 'test' | awk '{ 
    for (i=1; i <= NF; i++) { 
     sub(".", substr(toupper($i), 1,1) , $i); 
     print $i; 
     # or 
     # print substr(toupper($i), 1,1) substr($i, 2); 
    } 
}' 
+0

Ein bisschen Erklärung über das Beispiel oben: ** NF ** - Built-in awk Variablen aus Anzahl der Felder kommt (in der Regel zeigt, wie viele Leerzeichen getrennt Strings Sie auf eine Zeile haben) - in diesem Beispiel Es gibt 1 zurück ** substr ** - returns substring, die Deklaration sieht wie folgt aus ** substr (string, start, length) **. ** sub ** - Ersatzfunktion - ** sub (Regex, Ersatz, Ziel) ** –

+1

Hinweis: es ist wahrscheinlich etwas effizienter, toupper (substr (... 'anstelle von' substr (toupper (.. –

3

Hier ist eine Lösung, die die \u nicht verwendet, die nicht für alle seds gemeinsam ist.

Speichern Sie diese Datei in capitalize.sed, dann laufen sed -i -f capitalize.sed FILE

s:^:.: 
h 
y/qwertyuiopasdfghjklzxcvbnm/QWERTYUIOPASDFGHJKLZXCVBNM/ 
G 
s:$:\n: 
:r 
/^.\n.\n/{s:::;p;d} 
/^[^[:alpha:]][[:alpha:]]/ { 
    s:.\(.\)\(.*\):x\2\1: 
    s:\n\(..\):\nx: 
    tr 
} 

/^[[:alpha:]][[:alpha:]]/ { 
    s:\n.\(.\)\(.*\)$:\nx\2\1: 
    s:..:x: 
    tr 
} 
/^[^\n]/ { 
    s:^.\(.\)\(.*\)$:.\2\1: 
    s:\n..:\n.: 
    tr 
} 
1

Dies könnte für Sie arbeiten (GNU sed):

echo "aaa bbb ccc aaa-bbb-ccc aaa_bbb_ccc aaa-bbb_ccc" | sed 's/\<.\|_./\U&/g' 
Aaa Bbb Ccc Aaa-Bbb-Ccc Aaa_Bbb_Ccc Aaa-Bbb_Ccc 
0

alinsoar der Geist weht Lösung funktioniert nicht bei allen in Plan9 sed, oder richtig in busybox sed. Aber du solltest immer noch versuchen herauszufinden, wie es sein Ding machen soll: du wirst viel über sed lernen.

Hier ist eine nicht so clevere aber leichter zu verstehende Version, die zumindest in Plan9, busybox und GNU sed (und wahrscheinlich BSD und MacOS) funktioniert. Plan9 sed benötigt Backslashes, die im Match-Teil des Befehls s entfernt wurden.

#! /bin/sed -f 

y/PYFGCRLAOEUIDHTNSQJKXBMWVZ/pyfgcrlaoeuidhtnsqjkxbmwvz/ 

s/\(^\|[^A-Za-z]\)a/\1A/g 
s/\(^\|[^A-Za-z]\)b/\1B/g 
s/\(^\|[^A-Za-z]\)c/\1C/g 
s/\(^\|[^A-Za-z]\)d/\1D/g 
s/\(^\|[^A-Za-z]\)e/\1E/g 
s/\(^\|[^A-Za-z]\)f/\1F/g 
s/\(^\|[^A-Za-z]\)g/\1G/g 
s/\(^\|[^A-Za-z]\)h/\1H/g 
s/\(^\|[^A-Za-z]\)i/\1I/g 
s/\(^\|[^A-Za-z]\)j/\1J/g 
s/\(^\|[^A-Za-z]\)k/\1K/g 
s/\(^\|[^A-Za-z]\)l/\1L/g 
s/\(^\|[^A-Za-z]\)m/\1M/g 
s/\(^\|[^A-Za-z]\)n/\1N/g 
s/\(^\|[^A-Za-z]\)o/\1O/g 
s/\(^\|[^A-Za-z]\)p/\1P/g 
s/\(^\|[^A-Za-z]\)q/\1Q/g 
s/\(^\|[^A-Za-z]\)r/\1R/g 
s/\(^\|[^A-Za-z]\)s/\1S/g 
s/\(^\|[^A-Za-z]\)t/\1T/g 
s/\(^\|[^A-Za-z]\)u/\1U/g 
s/\(^\|[^A-Za-z]\)v/\1V/g 
s/\(^\|[^A-Za-z]\)w/\1W/g 
s/\(^\|[^A-Za-z]\)x/\1X/g 
s/\(^\|[^A-Za-z]\)y/\1Y/g 
s/\(^\|[^A-Za-z]\)z/\1Z/g