33

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?

kenorb
  • 155,785
  • 88
  • 678
  • 743
tsrrhhh
  • 459
  • 1
  • 5
  • 10

4 Answers4

31

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
Whymarrh
  • 13,139
  • 14
  • 57
  • 108
Will
  • 24,082
  • 14
  • 97
  • 108
  • it's suprising that no version number even in binary. thank you. very helpful! – tsrrhhh Jun 05 '16 at 08:47
  • No problem, glad to help! :) – Will Jun 05 '16 at 08:59
  • 2
    Although there's no official version number, the `strings` ouput is showing RCS versions and dates for 4 of the source code files. That should be sufficient, depending on why the version string is wanted. – William Pursell Jun 05 '16 at 12:38
  • also` PROJECT:text_cmds-88` as above. on Sierra 10.12.6. i get `@(#)PROGRAM:sed PROJECT:text_cmds-97` – ShpielMeister Sep 06 '18 at 00:02
  • @ShpielMeister is correct. That IS the version. It's even on Apple's website. You can actually obtain that string by `what(1)`. So basically although you're right in a sense your answer is not strictly true. – Pryftan Nov 11 '22 at 10:12
11

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
Bruno Bronosky
  • 66,273
  • 12
  • 162
  • 149
  • As to `sed -i`, why not [this](https://stackoverflow.com/a/22084103/3926735)? – zezollo Aug 15 '22 at 15:40
  • @zezollo Because the objective here is to detect the VERSION of `sed`, not find workarounds to edit in place. Bruno Bronosky is using the `-i` flag to ascertain whether or not the version of sed the user has installed POSSESSES that utility, thereby allowing him to leverage that critical information to further his deduction of the active version being examined. – NerdyDeeds Dec 25 '22 at 23:58
10

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.

scorgn
  • 3,439
  • 2
  • 20
  • 23
kdhp
  • 2,096
  • 14
  • 15
  • Sadly, versioning and standards affect even the example test script here. On macOS `10.14.5` (Mojave), the command line flag must have capital `V` in `-productversion`: `case $(sw_vers -productVersion) in`. This would return `10.14.5` on Mojave. However, the `bash` `case` statement `10.[45].*)` pattern matching then doesn't appear to work (facepalm). Ironic that some of the major differences between `sed` versions are POSIX EREs (extended regular expressions) which have to do with pattern matching. Probably needs this pattern added? `10.1[01234].*)` – TrinitronX Jun 11 '19 at 19:51
  • 1
    @TrinitronX Try the `what(1)` command instead. That will directly give you the right information. – Pryftan Nov 11 '22 at 10:12
  • @Pryftan : Good call! On Catalina, this returns: `what $(which sed)` => `/usr/bin/sed PROGRAM:sed PROJECT:text_cmds-101.40.1` The user would have to parse this information, but it would give a more accurate `sed` `txt_cmds` bundled tools version. – TrinitronX Nov 13 '22 at 04:46
0

Directly getting the version of different tools under macOS

There is a direct way to get the version of many tools in macOS and I believe this command also works under other BSDs. Here's an example of how to get the version of sed under macOS Ventura:

$ what /usr/bin/sed
/usr/bin/sed:
    PROGRAM:sed  PROJECT:text_cmds-154
    PROGRAM:sed  PROJECT:text_cmds-154

Now how do I know that this is the version? If you go to https://opensource.apple.com/releases/ and click on macOS and then expand macOS 13.0 you will see a bunch of tools and versions. Scroll down to text_cmds-154 and you notice that that's indeed the version.

You'll also find it gives two links: one to download and one to GitHub.

It's not the same as you'll find in say linux but it's the actual version.

I should point out that there's also a tool in some BSDs called ident(1) which might also give some information but I cannot confirm the contents of it without looking at the source code and I've not done that.

Pryftan
  • 192
  • 1
  • 6