Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

grep

sed

awk

For example

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

to print only abc-1234a

like image 588
user1224949 Avatar asked Sep 10 '12 23:09

user1224949


1 Answers

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
like image 82
ghoti Avatar answered Sep 28 '22 00:09

ghoti