2012-08-03 18 views
15

Ho tre tipi di stringhe che vorrei inserire in maiuscolo in uno script bash. Ho pensato che sed/awk sarebbe la mia migliore scommessa, ma non ne sono sicuro. Qual è il modo migliore in base ai seguenti requisiti?sed/awk in maiuscolo stringhe

1.) singola parola ad es. taco -> Taco

2.) più parole separate dai trattini ad es. my-fish-tacos -> My-Fish-Tacos

3.) più parole separate dai trattini di sottolineatura ad es. my_fish_tacos -> My_Fish_Tacos

risposta

26

Non c'è alcuna necessità di utilizzare i gruppi di cattura (anche se & è uno in un senso):

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

L'output:

Taco My-Fish-Tacos My_Fish_Tacos 

Il la maiuscola con escape "u" capitalizza il carattere successivo nella sottostringa corrispondente.

+0

Come posso modificare questo per gestire parole che sono tutte maiuscole? Ad esempio, my-FISH-TACOS dovrebbe ouput My-Fish-Tacos. – GregB

+4

@GregB: Dillo a caratteri minuscoli tutti i caratteri e poi a quelli maiuscoli: 'sed 's/[^ _-] */\ L \ u &/g'' –

+2

Nota: questa è un'estensione GNU sed.Gli utenti di BSD sed (incluso OS X) non possono farlo. – Jashank

6

provare quanto segue:

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

Funziona per me usando GNU sed, ma non credo BSD sed supporta \U e \L.

6

Utilizzando 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

Un po 'di spiegazione circa l'esempio precedente: ** ** NF - Built-in variabili awk viene dal numero di campi (mostra in genere il numero di spazi bianchi separati stringhe si dispone su una riga) - in questo esempio restituirà 1 ** substr ** - restituisce sottostringa, la dichiarazione è simile a questa ** substr (stringa, inizio, lunghezza) **. ** sub ** - funzione sostitutiva - ** sub (regex, replacement, target) ** –

+1

Nota: probabilmente è leggermente più efficiente usare 'toupper (substr (...' invece di 'substr (toupper (.. –

3

Ecco una soluzione che non utilizza lo \u, che non è comune a tutti i sed.

Salva questo file in capitalize.sed, quindi eseguire 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

Questo potrebbe funzionare per voi (GNU sed): soluzione di mind-blowing

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

di alinsoar non funziona affatto in Plan9 sed, o correttamente in busybox sed. Ma dovresti comunque cercare di capire come dovrebbe fare la sua cosa: imparerai molto su sed.

Ecco una versione non intelligente ma di più facile comprensione che funziona almeno in Plan9, busybox e GNU sed (e probabilmente BSD e MacOS). Plan9 sed ha bisogno di barre retroverse rimosse nella parte corrispondente del comando s.

#! /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