PsyKoptiK
PsyKoptiK

Reputation: 35

Count number of patterns with a single command

I'd like to count the number of occurrences in a string. For example, in this string :

'apache2|ntpd'

there are 2 different strings separated by | character. Another example :

'apache2|ntpd|authd|freeradius'

In this case there are 4 different strings separated by | character.

Would you know a shell or perl command that could simply count this for me?

Upvotes: 1

Views: 90

Answers (7)

SLePort
SLePort

Reputation: 15461

With wc and parameter expansion:

$ data='apache2|ntpd|authd|freeradius'
$ wc -w <<< ${data//|/ }
4

Using parameter expansion, all pipes are replaced with spaces. The result string is passed to wc -w for word count.

As @gniourf_gniourf mentionned, it works with what at first looks like process names but will fail if strings contain spaces.

Upvotes: 1

Mustafa DOGRU
Mustafa DOGRU

Reputation: 4112

you can use awk command as below;

echo "apache2|ntpd" | awk -F'|' '{print NF}'

-F'|' is to field separator; NF means Number of Fields

Example;

user@host:/tmp$ echo 'apache2|ntpd|authd|freeradius' | awk -F'|' '{print NF}'
4

you can also use this;

user@host:/tmp$ echo "apache2|ntpd" | tr '|' ' ' | wc -w
2
user@host:/tmp$ echo 'apache2|ntpd|authd|freeradius' | tr '|' ' ' | wc -w
4


tr '|' ' ' : translate | to space
wc -w : print the word counts

if there are spaces in the string, wc -w not correct result, so

echo 'apac he2|ntpd' | tr '|' '\n' | wc -l



user@host:/tmp$ echo 'apac he2|ntpd' | tr '|' ' ' | wc -w
3   --> not correct
user@host:/tmp$ echo 'apac he2|ntpd' | tr '|' '\n' | wc -l
2

 tr '|' '\n' : translate | to newline
 wc -l : number of lines

Upvotes: 3

Sanjay
Sanjay

Reputation: 2503

may be this will help you.

IN="apache2|ntpd"

mails=$(echo $IN | tr "|" "\n")

for addr in $mails
do
    echo "> [$addr]"
done

Upvotes: -1

James Brown
James Brown

Reputation: 37404

You could use awk to count the occurrances of delimiters +1:

$ awk '{print gsub(/\|/,"")+1}'  <(echo "apache2|ntpd|authd|freeradius")
4

Upvotes: 0

Chem-man17
Chem-man17

Reputation: 1770

You can do this with grep as well-

echo "apache2|ntpd|authd|freeradius" | grep -o "|" | wc -l
Output-
3

That output is the number of pipes.

To get the number of commands-

var=$(echo "apache2|ntpd|authd|freeradius" | grep -o "|" | wc -l)
echo $((var + 1))
Output - 
4

Upvotes: 0

Inian
Inian

Reputation: 85580

Another pure bash technique using positional-parameters

$ userString="apache2|ntpd|authd|freeradius"
$ printf "%s\n" $(IFS=\|; set -- $userString; printf "%s\n" "$#")
4

Thanks to cdarke's suggestion from the commands, the above command can directly store the count to a variable

$ printf -v count "%d" $(IFS=\|; set -- $userString; printf "%s\n" "$#")
$ printf "%d\n" "$count"
4

Upvotes: 1

cdarke
cdarke

Reputation: 44354

Do can do this just within bash without calling external languages like awk or external programs like grep and tr.

data='apache2|ntpd|authd|freeradius'
res=${data//[!|]/}
num_strings=$(( ${#res} + 1 ))
echo $num_strings

Let me explain.

res=${data//[!|]/} removes all characters that are not (that's the !) pipes (|).

${#res} gives the length of the resulting string.

num_strings=$(( ${#res} + 1 )) adds one to the number of pipes to get the number of fields.

It's that simple.

Upvotes: 1

Related Questions