# The key to getting this to work is to tell `sed` to exclude what you
# don't want to be output as well as specifying what you do want.
string='This is a sample 123 text and some 987 numbers'
echo "$string" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/\1 \2/p'
# This says:
#
# - don't default to printing each line (`-n`)
# - exclude zero or more non-digits
# - include one or more digits
# - exclude one or more non-digits
# - include one or more digits
# - exclude zero or more non-digits
# - print the substitution (`p`)
#
# In general, in `sed` you capture groups using parentheses and output
# what you capture using a back reference:
echo "foobarbaz" | sed 's/^foo\(.*\)baz$/\1/'
# will output "bar". If you use `-r` (`-E` for OS X) for extended regex,
# you don't need to escape the parentheses:
echo "foobarbaz" | sed -r 's/^foo(.*)baz$/\1/'
# There can be up to 9 capture groups and their back references. The
# back references are numbered in the order the groups appear, but they
# can be used in any order and can be repeated:
echo "foobarbaz" | sed -r 's/^foo(.*)b(.)z$/\2 \1 \2/'
# outputs "a bar a".
#
# If you have GNU `grep` (it may also work in BSD, including OS X):
echo "$string" | grep -Po '\d+'
# or variations such as:
echo "$string" | grep -Po '(?<=\D )(\d+)'
# The `-P` option enables Perl Compatible Regular Expressions. See [`man
# 3 pcrepattern`][1] or [`man
# 3 pcresyntax`][2].
#
# [1]: http://linux.die.net/man/3/pcrepattern
# [2]: http://linux.die.net/man/3/pcresyntax
#
# [Dennis Williamson] [so/q/2777579] [cc by-sa 3.0]
$
cheat.sh