user1224949 user1224949 - 4 years ago 89
Linux Question

How can i print the all the characters until a certain pattern(excluding the pattern itself) using grep/awk/sed.

For example

echo "abc-1234a :" | grep <do-something>

to just print abc-1234a

Answer Source

I think these are closer to what you're getting at, but without knowing what you're really trying to achieve, it's hard to say.

echo "abc-1234a :" | egrep -o '^[^:]+'

... though this will also match lines that have no colon. If you only want lines with colons, and you must use only 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 would be replace with possibly multiple lines of input.

The smallest tool you could use is probably cut:

echo "abc-1234a :" | cut -d: -f1

And sed is always available...

echo "abc-1234a :" | sed 's/ *:.*//'

For this last one, if you only want to print lines that include a colon, change it to:

echo "abc-1234a :" | sed -ne 's/ *:.*//p'

Heck, you could even do this in pure bash:

while read line; do
  # do stuff with $field
done <<<"abc-1234a :"

For information on the %% bit, you can man bash and search for "Parameter Expansion".


You said:

It's the characters in the first line of input before the colon. The input could have multiple line though.

The solutions with grep probably aren't your best choice, then, since they'll also print data from subsequent lines that might include colons. Of course, there are many ways to solve this requirement as well. We'll start with sample input:

$ function sample { printf "abc-1234a:foo\nbar baz:\nNarf\n"; }
$ sample
bar baz:

You could use multiple pipes, for example:

$ sample | head -1 | grep -Eo '^[^:]*'
$ sample | head -1 | cut -d: -f1      

Or you could use sed to process only the first line:

$ sample | sed -ne '1s/:.*//p'

Or tell sed to exit after printing the first line (which is faster than reading the whole file):

$ sample | sed 's/:.*//;q'

Or do the same thing but only show output if a colon was found (for safety):

$ sample | sed -ne 's/:.*//p;q'

Or have awk do the same thing (as the last 3 examples, respectively):

$ sample | awk '{sub(/:.*/,"")} NR==1'
$ sample | awk 'NR>1{nextfile} {sub(/:.*/,"")} 1'
$ sample | awk 'NR>1{nextfile} sub(/:.*/,"")'

Or in bash, with no pipes at all:

$ read line < <(sample)
$ printf '%s\n' "${line%%:*}"
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download