I have a variable which has a string stored in it and need to check if it has lines in it:

var=`ls "$sdir" | grep "$input"` 

pseudo-code:

while [ ! $var's number of lines -eq 1 ] do something 

That's my idea on how to check it. echo $var | wc -l doesn't work - it always says 1, even though it has 3.

echo -e doesn't work as well.

9 Answers

Quotes matter.

echo "$var" | wc -l 
10

The accepted answer and other answers posted here do not work in case of an empty variable (undefined or empty string).

This works:

echo -n "$VARIABLE" | grep -c '^' 

For example:

ZERO= ONE="just one line" TWO="first > second" echo -n "$ZERO" | grep -c '^' 0 echo -n "$ONE" | grep -c '^' 1 echo -n "$TWO" | grep -c '^' 2 
7

Another way using here strings in bash:

wc -l <<< "$var" 

As mentioned in this comment, an empty $var will result in 1 line instead of 0 lines because here strings add a newline character in this case (explanation).

11

A simpler version of @Julian's answer, that works for all strings, with or without trailing \n (it does count a file containing just a single trailing \n as empty):

printf "%s" "$a" | grep -c "^"

  • Returns zero: unset variable, empty string, string containing bare newline
  • Returns 1: any non-empty line, with or without trailing newline
  • etc

Output:

# a= # printf "%s" "$a" | grep -c "^" 0 # a="" # printf "%s" "$a" | grep -c "^" 0 # a="$(printf "")" # printf "%s" "$a" | grep -c "^" 0 # a="$(printf "\n")" # printf "%s" "$a" | grep -c "^" 0 # a="$(printf " \n")" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf " ")" # printf "%s" "$a" | grep -c "^" 1 # a="aaa" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf "%s" "aaa")" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf "%s\n" "aaa")" # printf "%s" "$a" | grep -c "^" 1 # a="$(printf "%s\n%s" "aaa" "bbb")" # printf "%s" "$a" | grep -c "^" 2 # a="$(printf "%s\n%s\n" "aaa" "bbb")" # printf "%s" "$a" | grep -c "^" 2 
2

No one has mentioned parameter expansion, so here are a couple of ways using pure bash.

Method 1

Remove non-newline characters, then get string length + 1. Quotes are important.

 var="${var//[!$'\n']/}" echo $((${#var} + 1)) 

Method 2

Convert to array, then get array length. For this to work, don't use quotes.

 set -f # disable glob (wildcard) expansion IFS=$'\n' # let's make sure we split on newline chars var=(${var}) echo ${#var[@]} 
4

You can substitute the "wc -l" with "wc -w" to rather count the number of words instead of lines. This will not count any new lines and can be used to test if your original results are empty before you continue.

1

The top voted answers fail if no results were returned by a grep.

Homer Simpson Marge Simpson Bart Simpson Lisa Simpson Ned Flanders Rod Flanders Todd Flanders Moe Szyslak 

This is the wrong way to do it:

wiggums=$(grep -iF "Wiggum" characters.txt); num_wiggums=$(echo "$wiggums" | wc -l); echo "There are ${num_wiggums} here!"; 

There will tell us, there is 1 Wiggum in the list, even if there aren't any.

Instead, you need to do one extra check to see if the variable is empty (-z, as in "is zero"). If grep didn't return anything, the variable will be empty.

matches=$(grep -iF "VanHouten" characters.txt); if [ -z "$matches" ]; then num_matches=0; else num_matches=$(echo "$matches" | wc -l); fi echo "There are ${num_matches} VanHoutens on the list"; 

Another method to count number of lines in a variable - assuming you did check it was successfully filled or it is not empty, for that just check $? after var subshell result affectation - :

readarray -t tab <<<"${var}" echo ${#tab[@]} 

readarray|mapfile is bash internal command which converts input file, or here string in this case, to array based on newlines.

-t flag prevents storing newlines at end of array's cells, useful for later use of stored values

Advantages of this method are :

  • no external command (wc, grep, ...)
  • no subshell (pipe)
  • no IFS issues (restore after modification, tricky to use with command-limited scope on internal commands, ...)

To avoid filename in "wc -l" command:

lines=$(< "$filename" wc -l) echo "$lines" 

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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