0

First I am executing the below command.

Command executed:

/app/zookeeper/zookeeper-3.4.10/bin/zkServer.sh status

Output of the command:

ZooKeeper JMX enabled by default
Using config: /app/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower

I want to grep with the word "follower" and print the total count of that word (grep 'follower' | wc -l).

Issue I am facing here is that I am not able to put the output of the command to a variable it is throwing "command not found".

-bash-4.2$ cat zookeeper.sh
#!/bin/bash
ZK_STATUS = ` /app/zookeeper/zookeeper-3.4.10/bin/zkServer.sh status `
ABC = $ZK_STATUS | grep 'follower' | wc -l
echo $ABC

Output:

-bash-4.2$ ./zookeeper.sh
ZooKeeper JMX enabled by default
Using config: /app/zookeeper/zookeeper-3.4.10/bin/../conf/zoo.cfg
./zookeeper.sh: line 2: ZK_STATUS: command not found
./zookeeper.sh: line 4: ABC: command not found
0
fra-san
  • 10,205
  • 2
  • 22
  • 43
  • 2
    Do you also want to count the word followers, if it happened to occur? I'm also noting that your code seems to try to count lines containing the word, not the word itself (if it was to occur several times in one line). Is that an issue? – Kusalananda May 15 '21 at 09:58

4 Answers4

3
  1. The errors are because you have spaces before and after the = in the assignment. This is an error in shell scripts.

    Use var=value, not var = value. Otherwise, the shell will try to execute a program called var - hence the command not found error messages.

  2. You need to use command substitution to get the output of a command into a variable. e.g.

    ZK_STATUS=$(/app/zookeeper/zookeeper-3.4.10/bin/zkServer.sh status)
    
  3. grep has a -c option to count the number of matching lines, so wc -l isn't needed.

    ZK_STATUS=$(/app/zookeeper/zookeeper-3.4.10/bin/zkServer.sh status)
    ABC=$(printf '%s' "$ZK_STATUS" | grep -c follower)
    

    Or, more directly,

    ABC=$(/app/zookeeper/zookeeper-3.4.10/bin/zkServer.sh status |
          grep -c follower)
    
  4. If you want to count each individual occurrence of follower (rather than just count the number of lines in which the word appears at least once) then you can't use grep -c.

    Instead, do something like:

    ABC=$(printf '%s' "$ZK_STATUS" | grep -o follower | wc -l)
    

    grep -o will print every match on its own line. wc -l then counts those lines.

cas
  • 78,579
  • ABC=$(printf '%s' "$ZK_STATUS" | grep -c follower) what does printf '%s' here? – Kamesh M May 15 '21 at 11:13
  • grep -c will display only count of lines where content occurs . suppose in same line if content occurs 3 times. grep -c it will print "1" where content 3 times – Praveen Kumar BS May 15 '21 at 12:17
  • @PraveenKumarBS yes. so does piping to wc -l. – cas May 15 '21 at 12:26
  • @KameshM '%s' is a printf format specification for a string of any length. echo would work just as well in this case, but I mostly prefer printf - it works in all situations, no matter what I'm printing, whereas echo can fail badly, depending on what I'm trying to print with it or which version of echo I'm using. See Why is printf better than echo? – cas May 15 '21 at 12:34
2

With GNU grep or compatible and a given non-empty string not containing newline nor NUL characters:

string=follower

To count the number of lines containing that string in the output of some cmd:

count=$(
  cmd | grep -cFe "$string"
)

To count the number of non-overlapping occurrences of that string:

count=$(
  cmd | grep -oFe "$string" | wc -l
)

For the number of possibly overlapping occurrences (for instance, to consider that there are 3 occurrences of did in dididid, not just 2):

count=$(
  cmd | grep -Poe "(?=\Q$string\E)." | wc -l
)

(here also assuming that $string doesn't contain \E)

If you want to find the $string as a whole word, for instance so as not to count the follower in followers or followership, you can add the -w option to those grep commands above. In effect that will look for occurrences of follower that are neither preceded nor followed by letters, digits or underscores (so called word characters). To also avoid counting anti-follower, you'll need to do the exclusion by hand:

count=$(
  cmd | grep -Poe "(?<![\w-])\Q$string\E(?![\w-])" | wc -l
)

However here, your problems are more about basic shell syntax.

To store the output of a command (minus the trailing newline characters) in a shell variable:

variable=$(cmd)

(no space on either side of =, and avoid the antiquated variable=`cmd` syntax).

To print the contents of a variable followed by one newline character, so as to feed to a command like those grep ones above:

printf '%s\n' "$variable" | grep ...

(don't use echo, remember to quote your parameter expansions when in list contexts)

Though in bash and other shells that have borrowed zsh's <<< operator, you can also do:

<<< "$variable" grep ...

In any case, if the aim is to check whether a variable contains at least one occurrence of the string, it should just be (with standard shell syntax):

case $variable in
  (*"$string"*) echo variable contains the string;;
  (*) echo It does not;;
esac

(here $string may contain newline characters).

Or to check it in the output of cmd:

if
  cmd | grep -qFe "$string"
then
  echo cmd output contains the string
else
  echo it does not
fi
0

You can get the required output in below command

/app/zookeeper/zookeeper-3.4.10/bin/zkServer.sh status  \
  | awk '{print gsub("follower",$0)}'

It will display how many times word "follower" occurs , In this example Considering output is a single line

  • 1
    your gsub() should be gsub("follower", ""), also note that based on OP accepted answer, that sounds xe wants count the total number of the word follower in a output, not count for every line of output. so you need count them all and print the total at the END – αғsнιη May 15 '21 at 12:39
  • grep -c "follower" will show count of lines whre follower content occurs, Suppose in output is single line follower occurs 3 times, As per question it shuld show 3 , but it will show 1 – Praveen Kumar BS May 15 '21 at 12:44
0

In (GNU) awk, set the RS to the word that you want to count and print NR-1 at the end.

cmd | awk -vRS='follower' 'END{print NR-1}'

  • Note that it gives 0 on the output of printf 'whatever follower'. It shouldn't be a problem if the output of cmd is valid text though (does end in a newline character unlike the output of that printf command). You could change it to awk -vRS='follower' 'END{print NR-(NR&&RT=="")}' to account for (non-text) outputs ending in follower – Stéphane Chazelas May 17 '21 at 11:07