How can I check the version of sed in OS X?

I know if sed is GNU version, version check can be done like

$ sed --version

But this doesn't work in OS X. How can I do that?


Solution 1:

This probably isn't the answer you're looking for, but you can't. Mac OS X sed has no option to show the version number.

There is not even a version number in the binary:

$ strings $(which sed)
$FreeBSD: src/usr.bin/sed/compile.c,v 1.28 2005/08/04 10:05:11 dds Exp $
$FreeBSD: src/usr.bin/sed/main.c,v 1.36 2005/05/10 13:40:50 glebius Exp $
$FreeBSD: src/usr.bin/sed/misc.c,v 1.10 2004/08/09 15:29:41 dds Exp $
$FreeBSD: src/usr.bin/sed/process.c,v 1.39 2005/04/09 14:31:41 stefanf Exp $
@(#)PROGRAM:sed  PROJECT:text_cmds-88
malloc
%lu: %s: unexpected EOF (pending }'s)
0123456789/\$
%lu: %s: command expected
%lu: %s: invalid command code %c
%lu: %s: command %c expects up to %d address(es), found %d
%lu: %s: unexpected }
%lu: %s: extra characters at the end of %c command
%lu: %s: command %c expects \ followed by text
%lu: %s: extra characters after \ at the end of %c command
%lu: %s: filename expected
w command
read command
branch
label
%lu: %s: empty label
%lu: %s: substitute pattern can not be delimited by newline or backslash
%lu: %s: unterminated substitute pattern
%lu: %s: extra text at the end of a transform command
%lu: %s: unterminated regular expression
%lu: %s: expected context address
realloc
%lu: %s: whitespace after %s
%lu: %s: duplicate label '%s'
%lu: %s: RE error: %s
%lu: %s: \ can not be used as a string delimiter
%lu: %s: newline can not be used as a string delimiter
%lu: %s: unbalanced brackets ([])
bin/sed
Unix2003
123456789
%lu: %s: \%c not defined in the RE
%lu: %s: unescaped newline inside substitute pattern
%lu: %s: unterminated substitute in regular expression
%lu: %s: more than one number or 'g' in substitute flags
%lu: %s: overflow in the 'N' substitute flag
%lu: %s: no wfile specified
%lu: %s: bad flag in substitute command: '%c'
%lu: %s: transform pattern can not be delimited by newline or backslash
%lu: %s: unterminated transform source string
%lu: %s: unterminated transform target string
%lu: %s: transform strings are not the same length
%lu: %s: undefined label '%s'
%lu: %s: unused label '%s'
Eae:f:i:ln
setlinebuf() failed
stdout
"%s"
 ..."
-i may not be used with stdin
stdin
rename()
%s: %s %s
in-place editing only
works for regular files
%s: name too long
%s/.!%ld!%s
%s: %s
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
first RE may not be empty
RE error: %s
%lu: %s: \%d not defined in the RE
COLUMNS
\abfrtv
\%03o

Solution 2:

Looking though the various version of sed in text_cmds there are not many changes.

  • 10.0.0 Used NetBSD sed from fall 1998
  • 10.3.0 Used FreeBSD sed from fall 2002 but left the man-page unchanged, adding -E extended regular expressions and -i in-place editing.
  • 10.4.0 Had some fixes for in-place editing, and changed the man-page to the FreeBSD man-page from fall 2004.
  • 10.5.0 Updated to FreeBSD sed from fall 2005, adding -l line-buffered output and more refinements/fixes to in-place editing.
  • 10.6.0 Added a reference to compat(5) in the man-page.

The version of the operating-system can be checked, instead of the sed utility, by either using uname -r or sw_vers -productVersion:

case $(sw_vers -productVersion) in
10.[012].*)     echo no in-place editig, EREs, or line-buffered output;;
10.[45].*)      echo no line-buffered output;;
10.[6789].*)    echo newest version as of writing;;
10.1[01].*)     echo newest version as of writing;;
esac

(BSD utilities are not versioned because they are considered part of their operating-system). For more see man sw_vers.

Solution 3:

It depends on "why" you want to check the version

OS Version

Since (as kdhp says) BSD considers tools like sed to be part of the OS, you can consider the OS version to be tool version so:

sed_version="$(sw_vers -productVersion)"
echo $sed_version
#output> 10.15.7

man date

sed_version="$(sed --version 2>&1 | grep -q GNU && sed --version | sed '1!d;s/.* //' || man sed | sed '$!d; s/ *BSD *//g')"
echo $sed_version
#output> May 10, 2005

Detect BSD/GNU in order to properly use features like -i

Since the BSD version doesn't have a --version option, you can trigger off that. (And that is safer than doing [[ $(uname) == Darwin ]] because some Linux people who are forced to use a Mac will make sed call gsed and cause themselves more trouble than they imagine.

function is_gnu_sed(){
  sed --version >/dev/null 2>&1
}

function sed_i_wrapper(){
  if is_gnu_sed; then
    $(which sed) "$@"
  else
    a=()
    for b in "$@"; do
      [[ $b == '-i' ]] && a=("${a[@]}" "$b" "") || a=("${a[@]}" "$b")
    done
    $(which sed) "${a[@]}"
  fi
}

date > /tmp/date
sed_i_wrapper -i s/2/X/g /tmp/date
cat /tmp/date
#output> Tue Dec X9 19:00:13 UTC X0X0