Counting number of single quotes in a string

i need to be able to count the number of single quotes

 '

in the entire string below:

"description":"DevOps- Test VM's, System Admins Test VM's ",

awk can most likely do this, but here's my attempt using egrep:

echo "${STRING}" | egrep -wc '"'"\'"'"'

or

echo "${STRING}" | egrep -wc ".*\'"

both of which do not even come close to doing what i want.

echo "${STRING}" | awk -F"'" '{print NF-1}'
4 Likes

Another one:

echo "${STRING}" | tr -cd "'" | wc -c
1 Like

Hi.

Also:

echo "$string" | tr -cd "'" | wc -c

producing:

2

for:

string="\"description\"":"\"DevOps- Test VM's, System Admins Test VM's \"",
$ echo "$string"
"description":"DevOps- Test VM's, System Admins Test VM's ",

Best wishes ... cheers, drl

1 Like

Longhand using builtins only and no pipes:-
(OSX 10.7.5 default bash terminal.)

#!/bin/bash
# Ensure string is complete!
txt=$(echo \"description\":\"DevOps- Test VM\'s, System Admins Test VM\'s \",)
echo "$txt"
subtext=""
char=0
count=0
while [ $char -lt ${#txt} ]
do
	subtext=$(printf "%02X" "'${txt:$char:1}")
	if [ "$subtext" == "27" ]
	then
		count=$((count+1))
	fi
	char=$(($char+1))
done
echo "Single quote occurs $count times..."

Results:-

AMIGA:barrywalker~/Desktop/Code/Shell> ./single_quote.sh
"description":"DevOps- Test VM's, System Admins Test VM's ",
Single quote occurs 2 times...
AMIGA:barrywalker~/Desktop/Code/Shell> _

EDIT:
Modified code to remove absolute (0X)27 value...

#!/bin/bash
# Ensure string is complete!
txt=$(echo \"description\":\"DevOps- Test VM\'s, System Admins Test VM\'s \",)
echo "$txt"
subtext=""
chr=$(printf "%02X" "''")
char=0
count=0
while [ $char -lt ${#txt} ]
do
	subtext=$(printf "%02X" "'${txt:$char:1}")
	if [ "$subtext" == "$chr" ]
	then
		count=$((count+1))
	fi
	char=$(($char+1))
done
echo "Single quote occurs $count times..."
2 Likes
#!/bin/bash

declare -i char=0 count=0 len=0

txt=$(echo \"description\":\"DevOps- Test VM\'s, System Admins Test VM\'s \",)
echo "$txt"
len=${#txt}

while (( char < len )) 
do
    [[ ${txt:char:1} == "'" ]] && (( count++ ))
    (( char++ ))
done

echo "Single quote occurs $count times..."
1 Like

I hate to bring the bad news but this is a subshell, not a builtin. This way your script takes perhaps eons more than any single pipeline (which is pretty similar to a subshell call).

Your idea can be realized using builtins only, like this (the following uses ksh88 , but should work in bash the same way):

#! /bin/ksh

typeset chString="\"description\":\"DevOps- Test VM\'s, System Admins Test VM\'s \""
typeset chBuffer=""
typeset chRemainder
typeset -i iCnt=0

while [ -n "$chString" ] ; do
     chRemainder="${chString#?}"               # "abc" -> "bc"
     chBuffer="${chString%${chRemainder}}"     # "abc" -> "a"
     chString="$chRemainder"                   # "abc" -> "bc"

     if [ "$chBuffer" == "'" ] ; then
          (( iCnt += 1 ))                      # in bash use (( iCnt++ ))
     fi
done

echo "$iCnt"

exit 0

I hope this helps.

bakunin

2 Likes

Yes, but a string does not necessarily consist of a single line (although it does in the example).

With awk one could try:

awk 'END{print NR-1}' RS=\' 

Probably safer to add them all up:

awk -F\' '{t+=NF-1} END{print t}' 
1 Like

Hi bakunin...

;oD

In my defence I was refering to the builtin commands not transient ones from the external storage source, (HDD).

As in my post very recently about the limitations of the default Android problem(s) how would I pipe to grep, awk, sed or anything else for the same problem?

Anyhow your info is much appreciated and logged inside the OLD grey matter... ;oD

1 Like

Hello skysmart,

Following may also help you in same.

awk -vs1="'" '{n=gsub(s1,X,$0);print n}'  Input_file
OR
awk -vs1="'" '{n+=gsub(s1,X,$0)} END{print n}'  Input_file (In case you need total number including all lines)

Thanks,
R. Singh

1 Like

I have understood that. The problem is the following: when the shell reads and executes shell code there are three possible ways to do that:

1) builtins: the shell executes them itself. This means there is a provision inside the shells binary code which gets executed. This is the case with builtins, reserved words (which is not the same, but for our purposes equal), variable expansion and similar syntactical devices. Into this group falls "if", "do", "while", "[[" (test), "((...))", etc..

2) externals: the shell simply loads and executes them. A separate process (child process) is created for every such binary.

3) process substitution/subshells: This is similar to externals but first a subshell is created as a child process and then the command is executed within this subshell. $( command1 [ | command2 | ... ] ) means: create a child process and start a shell there, then execute the shell code command1 [ | command2 | ... ] there, applying the same rules as if it where a one-line script. If command1 is a builtin it is processed like any builtin, but not from the original shell, though! It is processed by the child process. All this happens during commandline evaluation (of the main shell). Finally the output of the child shell is collected, the "$( ... )" is replaced by this collected output and the resulting line is executed.

You see, the process substitution involves the same process creation ( exec() , ...) as the external do. Even more so when the commands in the subshell are externals themselves.

I hope this helps.

bakunin

1 Like

Hi, for fun, builtin bash:

$ string="\"description\"":"\"DevOps- Test VM's, System Admins Test VM's \"",
$ echo $string 
"description":"DevOps- Test VM's, System Admins Test VM's ",
$ XX=${string//[^\']/}
$ echo ${#XX}
2
4 Likes