user1224949 user1224949 - 1 year ago 47
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
  field="${line%%:*}"
  # do stuff with $field
done <<<"abc-1234a :"

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

UPDATE:

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
abc-1234a:foo
bar baz:
Narf

You could use multiple pipes, for example:

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

Or you could 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 thing but only show output if a colon was found (for safety):

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

Or have awk do the same thing (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, with no pipes at all:

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