198

I have a textfile in which some words are printed in ALL CAPS. I want to be able to just convert everything in the textfile to lowercase, using sed. That means that the first sentence would then read, 'i have a textfile in which some words are printed in all caps.'

Gonzalo Matheu
  • 8,984
  • 5
  • 35
  • 58
magnetar
  • 6,487
  • 7
  • 28
  • 40
  • 11
    are you aware of the `tr` command? Sometimes it's more suitable than `sed`. – Bryan Oakley Dec 31 '10 at 14:25
  • @Bryan Oakley I wasn't until now. Thanks for pointing it out. But how do I use it to do what I was asking? – magnetar Jan 02 '11 at 12:40
  • look in the link provided in Raghuram's answer. – Bryan Oakley Jan 02 '11 at 14:21
  • 1
    if you must use sed, cat | sed 'y/ABCDEFÑØÅÆŒ/abcdefñøåæœ/' <- You must detail all the characters, uppercase to lowercase. I know it's cumbersome to write all those characters, but it will also work with all those international SPECIAL chars. :) – Arno Teigseth Nov 24 '13 at 15:03

9 Answers9

351

Here are two methods for doing the conversion using tr and sed:

Using tr

Convert uppercase to lowercase

tr '[:upper:]' '[:lower:]' < input.txt > output.txt

Convert lowercase to uppercase

tr '[:lower:]' '[:upper:]' < input.txt > output.txt

Using sed on GNU (but not BSD or Mac)

Convert uppercase to lowercase

sed -e 's/\(.*\)/\L\1/' input.txt > output.txt

Convert lowercase to uppercase

sed -e 's/\(.*\)/\U\1/' input.txt > output.txt
 

The reason the sed version doesn't work on BSD or Mac is because those systems don't support the \L or \U flags

Alan W. Smith
  • 24,647
  • 4
  • 70
  • 96
magnetar
  • 6,487
  • 7
  • 28
  • 40
  • 12
    I had to choose my own answer because I'm not a fan of answers that just consist of links. – magnetar Feb 03 '11 at 04:15
  • 8
    OSX doesn't support the GNU extensions either :( – ekkis Apr 03 '17 at 19:21
  • 8
    `sed -e 's/.*/\L&/' input.txt > output.txt` for GNU sed works fine too – Asfand Qazi Apr 13 '17 at 08:49
  • 1
    @ekkis OSX is using BSD (as mentioned, BSD sed doesn't support it). Try reading the top line of `man sed` to know which version you're using. – Ryder Dec 08 '17 at 10:48
  • 1
    For some reason when I use your upper case pattern, it adds a `U` in front of every line – Xtremefaith Dec 07 '18 at 06:06
  • In macOS, the workaround is to use GNU sed. Install first using `brew install gnu-sed`. And then to use GNU sed, use `gsed` instead of the macOS bundled `sed`. – GMaster Jul 04 '19 at 12:24
  • 2
    What does \1/ do at the end? – r_e Feb 12 '21 at 22:10
  • 1
    @r_e `\1` indicates the first "capture group" enclosed in parentheses. The `/` is part of the syntax for a substitution: `s///`. Thus, the text matched by the parenthesized capture group (`.*`) is output by the replacement. – NReilingh Apr 05 '21 at 06:42
74

If you have GNU extensions, you can use sed's \L (lower entire match, or until \L [lower] or \E [end - toggle casing off] is reached), like so:

sed 's/.*/\L&/' <input >output

Note: '&' means the full match pattern.

As a side note, GNU extensions include \U (upper), \u (upper next character of match), \l (lower next character of match). For example, if you wanted to camelcase a sentence:

$ sed -E 's/\w+/\u&/g' <<< "Now is the time for all good men..." # Camel Case
Now Is The Time For All Good Men...

Note: Since the assumption is we have GNU extensions, we can use sequences such as \w (match a word character) and the -E (extended regex) option, which relieves you of having to escape the one-or-more quantifier (+) and certain other special regex characters.

Grisha Levit
  • 8,194
  • 2
  • 38
  • 53
Luv2code
  • 1,079
  • 8
  • 14
  • 1
    Very useful tip. I've found that the round parentheses are not needed in the camel case example. 's/\w+/\u&/g' also works. – PJ_Finnegan Feb 26 '15 at 23:36
  • 1
    `sed -ri 's/MATCH_WHATEVER/\L&/i' input-file.ext` - using the `/i` modifier makes the match case-insensitive and thus is optional. The `-i` switch tells sed to alter the file in-place. No need to redirect output to another file if you don't have to. – Jim Dec 13 '16 at 01:08
  • 3
    I really needed this `\E [end - toggle casing off]`. Thank you ! – Mehdi Yedes Feb 14 '20 at 13:34
  • Note that the syntax generally seems to be `\L\1`, so `\L&` is an exception with the missing backslash. I tested this and if you add the backslash before the `&` you just get a literal `&`. – Roel Van de Paar Sep 26 '20 at 04:06
50

You also can do this very easily with awk, if you're willing to consider a different tool:

echo "UPPER" | awk '{print tolower($0)}'
iconoclast
  • 21,213
  • 15
  • 102
  • 138
whitehat237
  • 509
  • 4
  • 2
21

Here are many solutions :

To upercaser with perl, tr, sed and awk

perl -ne 'print uc'
perl -npe '$_=uc'
perl -npe 'tr/[a-z]/[A-Z]/'
perl -npe 'tr/a-z/A-Z/'
tr '[a-z]' '[A-Z]'
sed y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
sed 's/\([a-z]\)/\U\1/g'
sed 's/.*/\U&/'
awk '{print toupper($0)}'

To lowercase with perl, tr, sed and awk

perl -ne 'print lc'
perl -npe '$_=lc'
perl -npe 'tr/[A-Z]/[a-z]/'
perl -npe 'tr/A-Z/a-z/'
tr '[A-Z]' '[a-z]'
sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
sed 's/\([A-Z]\)/\L\1/g'
sed 's/.*/\L&/'
awk '{print tolower($0)}'

Complicated bash to lowercase :

while read v;do v=${v//A/a};v=${v//B/b};v=${v//C/c};v=${v//D/d};v=${v//E/e};v=${v//F/f};v=${v//G/g};v=${v//H/h};v=${v//I/i};v=${v//J/j};v=${v//K/k};v=${v//L/l};v=${v//M/m};v=${v//N/n};v=${v//O/o};v=${v//P/p};v=${v//Q/q};v=${v//R/r};v=${v//S/s};v=${v//T/t};v=${v//U/u};v=${v//V/v};v=${v//W/w};v=${v//X/x};v=${v//Y/y};v=${v//Z/z};echo "$v";done

Complicated bash to uppercase :

while read v;do v=${v//a/A};v=${v//b/B};v=${v//c/C};v=${v//d/D};v=${v//e/E};v=${v//f/F};v=${v//g/G};v=${v//h/H};v=${v//i/I};v=${v//j/J};v=${v//k/K};v=${v//l/L};v=${v//m/M};v=${v//n/N};v=${v//o/O};v=${v//p/P};v=${v//q/Q};v=${v//r/R};v=${v//s/S};v=${v//t/T};v=${v//u/U};v=${v//v/V};v=${v//w/W};v=${v//x/X};v=${v//y/Y};v=${v//z/Z};echo "$v";done

Simple bash to lowercase :

while read v;do echo "${v,,}"; done

Simple bash to uppercase :

while read v;do echo "${v^^}"; done

Note that ${v,} and ${v^} only change the first letter.

You should use it that way :

(while read v;do echo "${v,,}"; done) < input_file.txt > output_file.txt
Vouze
  • 1,678
  • 17
  • 10
  • \U and \L in sed examples are gnu extensions. Something to keep in mind if you want it to be more portable – yashma Aug 19 '21 at 23:22
17

I like some of the answers here, but there is a sed command that should do the trick on any platform:

sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'

Anyway, it's easy to understand. And knowing about the y command can come in handy sometimes.

Dennis
  • 189
  • 1
  • 3
  • 3
    This doesn't work for arbitrary international characters but does work for ASCII characters in OS/X – emrys57 Nov 06 '17 at 13:28
  • 1
    It certainly did the job for me. I have to admit it was the first time I used y command. Thanks! – monsune Jan 14 '20 at 21:23
13

If you have GNU sed (likely on Linux, but not on *BSD or macOS):

echo  "Hello  MY name is SUJIT "  | sed 's/./\L&/g'

Output:

hello  my name is sujit
David Jones
  • 4,766
  • 3
  • 32
  • 45
Sujit Dhamale
  • 1,311
  • 11
  • 14
4

If you are using posix sed

Selection for any case for a pattern (converting the searched pattern with this sed than use the converted pattern in you wanted command using regex:

echo "${MyOrgPattern} | sed "s/[aA]/[aA]/g;s/[bB]/[bB]/g;s/[cC]/[cC]/g;s/[dD]/[dD]/g;s/[eE]/[eE]/g;s/[fF]/[fF]/g;s/[gG]/[gG]/g;s/[hH]/[hH]/g;s/[iI]/[iI]/g;s/[jJ]/[jJ]/g;s/[kK]/[kK]/g;s/[lL]/[lL]/g;s/[mM]/[mM]/g;s/[nN]/[nN]/g;s/[oO]/[oO]/g;s/[pP]/[pP]/g;s/[qQ]/[qQ]/g;s/[rR]/[rR]/g;s/[sS]/[sS]/g;s/[tT]/[tT]/g;s/[uU]/[uU]/g;s/[vV]/[vV]/g;s/[wW]/[wW]/g;s/[xX]/[xX]/g;s/[yY]/[yY]/g;s/[zZ]/[zZ]/g" | read -c MyNewPattern
 YourInputStreamCommand | egrep "${MyNewPattern}"

convert in lower case

sed "s/[aA]/a/g;s/[bB]/b/g;s/[cC]/c/g;s/[dD]/d/g;s/[eE]/e/g;s/[fF]/f/g;s/[gG]/g/g;s/[hH]/h/g;s/[iI]/i/g;s/j/[jJ]/g;s/[kK]/k/g;s/[lL]/l/g;s/[mM]/m/g;s/[nN]/n/g;s/[oO]/o/g;s/[pP]/p/g;s/[qQ]/q/g;s/[rR]/r/g;s/[sS]/s/g;s/[tT]/t/g;s/[uU]/u/g;s/[vV]/v/g;s/[wW]/w/g;s/[xX]/x/g;s/[yY]/y/g;s/[zZ]/z/g"

same for uppercase replace lower letter between // by upper equivalent in the sed

Have fun

kleopatra
  • 51,061
  • 28
  • 99
  • 211
NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43
  • (I found this one worked best on MacOS) - Nice, my friend - but a tiny topo - you have the Jj case backwards. Should be sed "s/[aA]/a/g;s/[bB]/b/g;s/[cC]/c/g;s/[dD]/d/g;s/[eE]/e/g;s/[fF]/f/g;s/[gG]/g/g;s/[hH]/h/g;s/[iI]/i/g;s/[jJ]/j/g;s/[kK]/k/g;s/[lL]/l/g;s/[mM]/m/g;s/[nN]/n/g;s/[oO]/o/g;s/[pP]/p/g;s/[qQ]/q/g;s/[rR]/r/g;s/[sS]/s/g;s/[tT]/t/g;s/[uU]/u/g;s/[vV]/v/g;s/[wW]/w/g;s/[xX]/x/g;s/[yY]/y/g;s/[zZ]/z/g" – Goblinhack Jun 16 '15 at 02:05
  • 1
    I'm not sure why you need to do something so labor intensive. I'm assuming Mac OS does not have GNU extensions, but if you're dead set on using sed, instead of substitution ('s') you could use transliteration ('y') like so: sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' – Luv2code Jun 27 '15 at 03:48
  • the goal was to select any text pattern that look like a lower/upper case from a non GNU sed without changing the content of the data source (a `y//` change the content of source or could miss the pattern search. – NeronLeVelu Jul 14 '15 at 06:19
3

short, sweet and you don't even need redirection :-)

perl -p -i -e 'tr/A-Z/a-z/' file
Lucifer
  • 29,392
  • 25
  • 90
  • 143
pedrito
  • 39
  • 1
  • Hah, well I tried to use this with a look behind and it somehow replaced most of all letters in my files with other random upper case letter. Gave me a good laugh anyway. I was able to to derive what I wanted from this answer too about perl: http://askubuntu.com/a/527073/250556 – ThorSummoner Jul 14 '15 at 23:00
0

Instead of typing this long expression:

sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' input

One could use this:

sed 'y/'$(printf "%s" {A..Z} "/" {a..z} )'/' input
s.ouchene
  • 1,682
  • 13
  • 31