I think that they are closer to what you get, but not knowing what you are really trying to achieve, it's hard to say.
echo "abc-1234a :" | egrep -o '^[^:]+'
... although this will also correspond to lines that do not have a colon. If you only want colon strings, and you should only use grep, this might work:
echo "abc-1234a :" | grep : | egrep -o '^[^:]+'
Of course, this only makes sense if your echo "abc-1234a :" is an example that will replace perhaps a few lines of input.
The smallest tool you could use is probably cut :
echo "abc-1234a :" | cut -d: -f1
And sed always available ...
echo "abc-1234a :" | sed 's/ *:.*//'
For this last, if you only want to print lines containing a colon, change it to:
echo "abc-1234a :" | sed -ne 's/ *:.*//p'
Damn, you could do this in pure bash:
while read line; do field="${line%%:*}"
For information on the %% bit, you can man bash and find "Parameter Extension".
UPDATE
You said:
These are the characters in the first line of input before the colon. input may contain several lines.
grep solutions are probably not your best bet, as they will also print data from subsequent lines, which may include colons. Of course, there are many ways to solve this requirement. We will start by entering a sample:
$ function sample { printf "abc-1234a:foo\nbar baz:\nNarf\n"; } $ sample abc-1234a:foo bar baz: Narf
You can use several channels, for example:
$ sample | head -1 | grep -Eo '^[^:]*' abc-1234a $ sample | head -1 | cut -d: -f1 abc-1234a
Or you can use sed to process only the first line:
$ sample | sed -ne '1s/:.*//p' abc-1234a
Or tell sed to exit after printing the first line (which is faster than reading the whole file):
$ sample | sed 's/:.*//;q' abc-1234a
Or do the same, but show the result only if the colon was found (for security):
$ sample | sed -ne 's/:.*//p;q' abc-1234a
Or try awk to do the same (as the last 3 examples, respectively):
$ sample | awk '{sub(/:.*/,"")} NR==1' abc-1234a $ sample | awk 'NR>1{nextfile} {sub(/:.*/,"")} 1' abc-1234a $ sample | awk 'NR>1{nextfile} sub(/:.*/,"")' abc-1234a
Or in bash, without pipes at all:
$ read line < <(sample) $ printf '%s\n' "${line%%:*}" abc-1234a