Correctly count number of lines a bash variable
Asked Answered
L

4

7

I need to count the number of lines of a given variable. For example I need to find how many lines VAR has, where VAR=$(git log -n 10 --format="%s").

I tried with echo "$VAR" | wc -l), which indeed works, but if VAR is empty, is prints 1, which is wrong. Is there a workaround for this? Something better than using an if clause to check whether the variable is empty...(maybe add a line and subtract 1 from the returned value?).

Libelee answered 19/5, 2014 at 11:27 Comment(4)
you want to exclude all empty lines or only if there is a single empty line?Capillary
git log produces either nothing, either some lines. So I need to treat the case of an empty var, because there won't be blank lines if the variable is not empty.Libelee
It's not true! git log -n 10 do generate empty lines. but I get what you want.Capillary
Sorry I haven't written the complete example. I am using format, so I don't have empty lines: git log -n 10 --format="%s".Libelee
S
14

The wc counts the number of newline chars. You can use grep -c '^' for counting lines. You can see the difference with:

#!/bin/bash

count_it() {
    echo "Variablie contains $2: ==>$1<=="
    echo -n 'grep:'; echo -n "$1" | grep -c '^'
    echo -n 'wc  :'; echo -n "$1" | wc -l
    echo
}

VAR=''
count_it "$VAR" "empty variable"

VAR='one line'
count_it "$VAR" "one line without \n at the end"

VAR='line1
'
count_it "$VAR" "one line with \n at the end"

VAR='line1
line2'
count_it "$VAR" "two lines without \n at the end"

VAR='line1
line2
'
count_it "$VAR" "two lines with \n at the end"

what produces:

Variablie contains empty variable: ==><==
grep:0
wc  :       0

Variablie contains one line without \n at the end: ==>one line<==
grep:1
wc  :       0

Variablie contains one line with \n at the end: ==>line1
<==
grep:1
wc  :       1

Variablie contains two lines without \n at the end: ==>line1
line2<==
grep:2
wc  :       1

Variablie contains two lines with \n at the end: ==>line1
line2
<==
grep:2
wc  :       2
Suck answered 19/5, 2014 at 11:41 Comment(1)
Great suggestion using grep -c '^' for this.Libelee
U
6

You can always write it conditionally:

[ -n "$VAR" ] && echo "$VAR" | wc -l || echo 0

This will check whether $VAR has contents and act accordingly.

Unbeliever answered 19/5, 2014 at 11:36 Comment(2)
It was a bit long, that's why thought there is some better way.Libelee
As soon as it gets this quirky I'd probably take the safe route and write it explicitly.Unbeliever
M
5

For a pure bash solution: instead of putting the output of the git command into a variable (which, arguably, is ugly), put it in an array, one line per field:

mapfile -t ary < <(git log -n 10 --format="%s")

Then you only need to count the number of fields in the array ary:

echo "${#ary[@]}"

This design will also make your life simpler if, e.g., you need to retrieve the 5th commit message:

echo "${ary[4]}"
Merci answered 19/5, 2014 at 12:53 Comment(0)
A
2

try:

echo "$VAR" | grep ^ | wc -l
Ahriman answered 19/5, 2014 at 11:44 Comment(1)
:) or simpler: grep -c '^' - see my answer.. ;)Suck

© 2022 - 2024 — McMap. All rights reserved.