63

How do you replace the first letter of a word into Capital letter, e.g.

Trouble me
Gold rush brides

into

Trouble Me
Gold Rush Brides
jasonleonhard
  • 12,047
  • 89
  • 66
neversaint
  • 60,904
  • 137
  • 310
  • 477
  • 1
    Duplicate - http://stackoverflow.com/questions/880597/how-can-i-capitalize-the-first-letter-of-each-word – Salgar Oct 08 '09 at 16:11

11 Answers11

103

This line should do it:

sed -e "s/\b\(.\)/\u\1/g"
tangens
  • 39,095
  • 19
  • 120
  • 139
  • 31
    Note: only works with GNU sed. If you're in OSX, FreeBSD, etc. this does nothing. – ghoti Aug 12 '15 at 15:34
  • 3
    Can you describe what the command is doing? The man page, for example, doesn't list this. – Ken Sharp Mar 25 '17 at 03:18
  • 5
    It's telling sed to convert the character after each word boundry to uppercase. \b is word boundry. Check out www.rexegg.com for some great tables of useful regular expression symbols. – xizdaqrian May 08 '17 at 08:01
  • 4
    The key here is the `\u` token, which will uppercase the next character. For a better reference see the `Escape sequences` section of [this link](https://perldoc.perl.org/perlre.html). – Gus Apr 05 '19 at 12:43
  • could you give some methods that work on macosx,thanks! @ghoti – Princekin Apr 16 '20 at 03:44
  • @lslboy, not an easy task in sed without GNU sed's `\u` to force case on the match on-the-fly. One could conceivably do this in a longer sed script, but a different language would let you do it more easily. For shell access and portability, I'd probably use `awk` instead. `awk '{for(i=1;i<=NF;i++){sub(".",toupper(substr($i,1,1)),$i)}}1'` might be sufficient. If you need to maintain word boundaries, then more code is required, but it's still easier in awk than in sed. – ghoti Apr 16 '20 at 06:46
  • I find a easy way in macosx,you can try it, `echo NaMe is | perl -pe 's/([a-z])/\u\1/g'` it work for me in macosx! – Princekin Apr 16 '20 at 07:53
  • 3
    @lslboy .. not quite. The task was to capitalize just the first letter of each word, and your solution capitalizes everything. the [`tr(1)`](http://manpages.debian.org/tr) command could likely do that more easily. With perl, consider instead, `perl -pe 's/\b(.)/\u\1/g'`. The `\b` identifies a word boundary. But note that this still uses `\u`, which is a Perl RE extension, not supported universally by non-perl tools like sed. – ghoti Apr 20 '20 at 16:19
  • For those on macOS, you can use homebrew to easily install GNU sed which has this feature. `brew install gnu-sed`. Then just use `gsed` instead of `sed`. – Chris May 25 '21 at 23:36
35

Using awk:

awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,1,1)) substr($i,2) }}1' file

The output would be:

Trouble Me
Gold Rush Brides
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
24

Use the following sed command for capitalizing the first letter of the each word.

echo -e "Trouble me \nGold rush brides" | sed -r 's/\<./\U&/g'

output

Trouble Me
Gold Rush Brides

The -r switch tells sed to use extended regular expressions. The instructions to sed then tell it to "search and replace" (the s at the beginning) the pattern \<. with the pattern \U& globally, i.e. all instances in every line (that's the g modifier at the end). The pattern we're searching for is \<. which is looking for a word boundary (\<) followed by any character (.). The replacement pattern is \U&, where \U instructs sed to make the following text uppercase and & is a synonym for \0, which refers to "everything that was matched". In this case, "everything that was matched" is just what the . matched, as word boundaries are not included in the matches (instead, they are anchors). What . matched is just one character, so this is what is upper cased.

dionyziz
  • 2,394
  • 1
  • 23
  • 29
rekha_sri
  • 2,677
  • 1
  • 24
  • 27
  • 9
    It is so much nicer when I don't have to do `man sed` to understand answers, because the answer contains an explanation for its contents. Maybe you would consider providing an explanation for your answer? – Jonathan Komar Aug 09 '15 at 20:39
  • 3
    @JonathanKomar Edited as you requested :) – dionyziz Jan 22 '19 at 10:30
8

Another shorter version with sed:

sed -e "s/\b./\u\0/g"
chtimi59
  • 469
  • 6
  • 9
5

I had apostrophes so, working off the first solution...

mike@mike-laptop3:~$ echo "BEST WESTERN PLUS BOB's INN" | tr "[A-Z]" "[a-z]" | sed -e "s/\b\(.\)/\u\1/g"

Best Western Plus Bob'S Inn

mike@mike-laptop3:~$ echo "BEST WESTERN PLUS BOB's INN" | tr "[A-Z]" "[a-z]" | sed "s/\( \|^\)\(.\)/\1\u\2/g"

Best Western Plus Bob's Inn

Karu
  • 4,512
  • 4
  • 30
  • 31
mikejonesey
  • 190
  • 1
  • 5
  • 3
    this helps as well if you have capital letters all over, but you only want the FIRST letter of each word to be capital – Botond Oct 28 '16 at 11:58
3

I know you said sed, but for shell scripting one of the easiest and more flexible for me was using Python which is available in most systems:

$ echo "HELLO WORLD" | python3 -c "import sys; print(sys.stdin.read().title())"
Hello World

For example:

$ lorem | python3 -c "import sys; print(sys.stdin.read().title())"
Officia Est Omnis Quia. Nihil Et Voluptatem Dolor Blanditiis Sit Harum. Dolore Minima Suscipit Quaerat. Soluta Autem Explicabo Saepe. Recusandae Molestias Et Et Est Impedit Consequuntur. Voluptatum Architecto Enim Nostrum Ut Corrupti Nobis.

You can also use things like strip() to remove spaces, or capitalize():

$ echo "  This iS mY USER ${USER}   " | python3 -c "import sys; print(sys.stdin.read().strip().lower().capitalize())"
This is my user jenkins
Havok
  • 5,776
  • 1
  • 35
  • 44
3

Using bash (without sed, so a little off topic):

msg="this is a message"
for word in $msg
do
   echo -n ${word^} ""
done

This Is A Message
2

Using sed with tr:

name="athens"
echo $name | sed -r "s/^[[:alpha:]]/$(echo ${name:0:1} | tr [[:lower:]] [[:upper:]])/"
mark_infinite
  • 383
  • 1
  • 7
  • 13
  • Nice solution! (Use `-E` instead of `-r` on MacOS.) I'm using this from a Makefile (bmake) and the command I used is slightly different: `CPP_STYLE_NS!=bash -c 'export CLASS_NAME="${CLASS_NAME}"; echo $${CLASS_NAME} | sed -E "s/^./$$(tr [:lower:] [:upper:] <<< $${CLASS_NAME:0:1})/g"'` (Massage a given name string.) – gone Jul 25 '21 at 17:31
2

Capitalize the first letter of each word (first lowercase everything, then uppercase the first letter).

echo "tugann sí spreagadh" | sed -E 's/.*/\L&/g' | sed -E 's/(\b.)/\U\1/g'
> Tugann Sí Spreagadh
fmassica
  • 1,896
  • 3
  • 17
  • 22
1

Proposed sed solutions until now will only work if the original text is in lowercase. Although one could use tr '[[:upper:]]' '[[:lower:]]' to normalize the input to lowercase, it may be convenient to have an all-in-one sed solution :

sed 's/\w\+/\L\u&/g'

This will match words (\w means word character, and \+ at least one and until the next non-word character), and lowercase until the end (\L) but uppercase the next (i.e. first) character (\u) on each (g) matched expression (&).

[Credits]

Skippy le Grand Gourou
  • 6,976
  • 4
  • 60
  • 76
0

Late post, but using ex (or vi) is POSIX (like the awk suggestion above) so it should work on any system that ships a proper "vi" implementation. FWIW, Busybox does not make the grade here.

POSIX sed only supports BREs and I personally do not advocate relying on GNU extensions if you have a choice.

However, POSIX ex/vi supports a few ERE features, including the word boundary < and the \U switch. If your platform does not have a compliant ex/vi then you have bigger problems than EREs, IMO.

As a bonus, a wq! will optionally perform an "in-place" edit.

cat <<EOF > casing.txt
Trouble me
Gold rush brides
EOF
ex -s casing.txt <<'EOF'
%s/\<./\U&/g
%p
wq!
EOF
Kajukenbo
  • 109
  • 1
  • 4