Simple sed replacement of tabs mysteriously failing

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.


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

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.