0

How would I parse following output of lein test

$ lein test
lein test nepleaks-engine.core-test

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

Where I want is get number before failures using bash script.

I only know better is grep,

$ lein test | grep 'failures' | cut -d' ' -f1
0 

Suggest me the better ways of doing this.

3

There is nothing wrong with the way that you are doing it, provided that failures will only occur on one line of the output. Another option might be to anchor on the fact that the number of failures is always on the 4th line of output. This is very easy with awk:

lein test | awk 'NR==4 { print $1 }'

Or to anchor on a line where failures, is the second field:

lein test | awk '$2=="failures," { print $1 }'

Or to anchor on the last line:

lein test | awk 'END { print $1 }'

Or using sed to anchor on the last line:

lein test | sed -n '$ s/^\([0-9]*\).*/\1/p'
| improve this answer | |
  • I think lein test | awk '$2=="failures," { print $1 }'is the safest one. – prayagupd Jun 12 '14 at 19:11
4

Your solution returns the part of every line that contains "failures" up to the first space character.

If you want to be more specific, you could do:

sed -n '$s/^\([[:digit:]]\{1,\}\) failures.*/\1/p'

That is, only consider the last line ($), and only if it follows a specific pattern: any non-empty sequence of decimal digits followed by  failures (and return that sequence of digits).

| improve this answer | |
1

With awk (print $1, means first column):

lein test | grep 'failures' | awk '{print $1}'
| improve this answer | |
  • 1
    You don't need the additional grep there. awk '/failures/{print $1}' achieves the same thing. Even better, match the output completely. awk '/^[[:digit:]]+ failures, [[:digit:]]+ errors/{print $1}' – Matt Jun 12 '14 at 13:13
  • Thanks. It was just to have an example there was close to his snippets also :-) – Adionditsak Jun 12 '14 at 13:31
1

Try this:

lein test | tail -n 1 | tr -s " " "\n" | head -n 1

How does it work?

  • tail -n 1 takes the last line
  • tr -s " " "\n" replaces all spaces with the new line character. It's a nice trick to tokenize the input by some character.
  • head -n 1 takes the first line
| improve this answer | |
  • nice trick. Loved it. – prayagupd Jun 17 '14 at 14:13
1

Through awk,

lein test | awk '/ failures,/{print $1}'

And with GNU sed,

lein test | sed -n '/ failures,/s/^\([^ ]\+\).*/\1/p'

Or portably:

lein test | sed -n '/ failures,/s/^\([^ ]\{1,\}\).*/\1/p'
| improve this answer | |
  • Note that \+ and \? here are GNU extensions and don't work with all versions of sed. Surely all you want is just * anyway? – Graeme Jun 12 '14 at 12:38
  • Then this command will works for all kind of sed's sed -n '/ failures,/s/^\([^ ]\{1,\}\).*/\1/p' – Avinash Raj Jun 12 '14 at 12:41
  • Or just s/^\([^ ]*\).*/\1/ is all you need for the replace part in this case. – Graeme Jun 12 '14 at 12:45
1

Considering the output, maybe (if you have the GNU implementation of grep):

lein test | grep -m 1 -o '^[[:digit:]]*'

Safer, with the same implementation:

lein test | grep -E 'failures.*errors' | grep -o '^[[:digit:]]*'

From the manpages:

-o, --only-matching

Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line.

-m NUM, --max-count=NUM

Stop reading a file after NUM matching lines.[...]

| improve this answer | |
  • 1
    That's likely to catch wrong input, considering the real world =) – Matt Jun 12 '14 at 13:16
0

You could try using this code:

lein test | tail | tr " " "\n" | head -1

which should give you what you want.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.