This ought to be really simple, but for some reason it is not working:

sed -i.bak -E 's/\t/  /' file.txt

Instead of replacing tab characters, it's replacing t characters. I've tried every variation on this I could think of, playing with quoting, etc. I've Googled and found everyone else using pretty similar expressions and they seem to work for them.

The -E is an OS X thing. I thought the failure might be a result of some weird quirk of OS X's sed, so I tried it with Ruby as well (without the -i), and got the same result:

ruby -pe '$_.gsub!(/\t/,"  ")' < file.txt > file.new

I'm using Bash 3.2.51 on OS X, and iTerm, although I can't see how any of those could be terribly relevant. I haven't set any weird environment variables, though I can post any that you think might be relevant.

What could be wrong?

UPDATE: I must have made some other mistake or typo when I tried the Ruby version, since Gilles points out that it does work (and I've never had him steer me wrong!). I'm not sure what happened, but I'm pretty sure it must have been my mistake.

  • 5
    May be you should try to replace the \t in the sed statement with CTRL-V<TAB> where <TAB> is the tab key and CTRL-V is control key and v pressed together.
    – unxnut
    Commented Jul 18, 2014 at 14:25
  • if ruby is also getting wrong answer, then it could be your regexp library. (I have tested both your commands, and both replace tab with 2 spaces.) It so then hopefully if you install Gnu sed it will also install the correct library. Commented Jul 18, 2014 at 16:44

10 Answers 10


The syntax \t for a tab character in sed is not standard. That escape is a GNU sed extension. You find a lot of examples online that use it because a lot of people use GNU sed (it's the sed implementation on non-embedded Linux). But OS X sed, like other *BSD sed, doesn't support \t for tab and instead treats \t as meaning backslash followed by t.

There are many solutions, such as:

  • Use a literal tab character.

    sed -i.bak 's/  /  /' file.txt
  • Use tr or printf to produce a tab character.

    sed -i.bak "s/$(printf '\t')/  /" file.txt
    sed -i.bak "s/$(echo a | tr 'a' '\t')/  /" file.txt
  • Use bash's string syntax allowing backslash escapes.

    sed -i.bak $'s/\t/  /' file.txt
  • Use Perl, Python or Ruby. The Ruby snippet that you posted does work.

  • For sed scripts which are contained in a ...sed script (used via -f option), the literal tab characters seem the only possibility to me. When editing this with vim, set noexpandtab is important.
    – Tobias
    Commented Jan 11, 2018 at 11:46
  • Warning: Only use that "literal tab character" technique if you want your coworker to come back behind you and break your script later. Only use that tr technique if you want your coworker to stab you in the face when they read your script. Commented Sep 6, 2018 at 18:50
  • Is the second double-quotation mark misplaced in the second block of code? I had to move it to where the closing single-quote currently is. Commented Dec 24, 2018 at 22:54
  • Thanks for the link to the bash string syntax... I had no idea (and this is the best option, IMHO).
    – levigroker
    Commented Oct 24, 2019 at 0:58
  • 1
    @Josh Double the backslash: if you write sed $'…\\…', sed sees …\… Commented Oct 24, 2019 at 21:26

Use a Bash specific quoting which lets you use strings like in C, so that a real tab character is passed to sed, not an escape sequence:

sed -i.bak -E $'s/\t/  /' file.txt
  • 1
    Also called "ANSI-C" quoting if others want to look up more info about it.
    – wisbucky
    Commented Jun 24, 2016 at 23:28
  • 2
    Seems to work on any bourne shell, works on non-bash UNIXes as well. Doesn't work on csh-variants though.
    – jornane
    Commented Nov 15, 2016 at 14:43
sed -i $'s/\t/  /g' file.txt 

works for me on OS X and is the same command i use on linux all the time.

  • Note that this replaces all tabs on every row whereas the OP intends to only replace the first (judging from the command they use).
    – Kusalananda
    Commented Sep 26, 2017 at 19:33

As noted, not all sed implementations support the notation of \t as a horizontal tab.

You can easily achieve your substitution with:

 perl -pi.old -e 's{\t+}{ }g' file.txt

This performs an in situ replacment which preserves your original file as "*.old". Perl allows alternate delimiters for the classic / making the expression much more readable (i.e. devoid of the "leaning toothpick" syndrome).

The + says one or more repetitions of a tab character are to be replaced. The g modifier enables global replacements throughout the end of each line.


If you want a more powerful sed (supporting \t and more) than the one on OS X, install GNU sed.

  • Since it didn't work with Ruby either, I'm not sure why I would conclude that OS X's sed is the problem. Do you have a reason to believe that's the problem? I'd be happy to install GNU sed if I had reason to believe it would solve the problem, but it seems like I've pretty much ruled that out.
    – iconoclast
    Commented Jul 18, 2014 at 15:36
  • With Ruby, you'll have to use only one backslash: ruby -pe '$_.gsub!(/\t/," ")' < file.txt
    – vinc17
    Commented Jul 18, 2014 at 15:45

You can also use echo inside sed:

sed -i "s/$(echo '\t')//g"

  • Note that echo '\t' will just output \t in some shells' implementation of echo.
    – Kusalananda
    Commented Jun 13, 2019 at 10:54
  • You'll need the -e option: echo -e '\t'
    – wrlee
    Commented Mar 15, 2023 at 15:50

If it is okay to require bash or zsh as a shell, then this is the easiest solution I can think of:

sed "s/$(echo -n -e "\t")/ /" file.txt

Note however, that echo flags (-n and -e) are undefined in POSIX, so a POSIX conform shell doesn't require to understand theses flags, yet many will for compatibility reasons.


Drawing from the above answers, here is a simple copy-and-pasteable version that works on OS X and you don't have to think about.

mysql -h myhost.com -u username -p  -e "select * from users;" -B --raw  | sed $'s/\t/,/g' > filename.csv

The $ in the sed command is the magic that makes it work.


I'm surprised no one suggested the very simple solution of: sed -i.bak -E 's/\\\t/ /' file.txt That should do the trick.

You need to escape the escape (hence the 3 \s) to allow sed to understand that you are trying to use a \t character in the regular expression when everything is substituted...

  • Why three backslashes specifically? Commented Jan 14, 2016 at 0:19
  • 3
    If I use GNU sed, one \ is enough, as no escaping is necessary. The problem is that BSD sed does not support this syntax for tabs.
    – iconoclast
    Commented Jan 16, 2016 at 16:43
  • Does not work on my El Capitan. Commented Jun 19, 2016 at 6:46
  • Gives me literally \t on Mojave
    – David
    Commented Nov 5, 2020 at 13:00

This worked for me.

sed -e 's/[\t]/ /g'

  • 3
    This is because you use GNU sed. This is not what the OP uses.
    – Kusalananda
    Commented Sep 26, 2017 at 19:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .