BASH - Count the number of occurrences of a substring in a string
How can I count the number of occurrences of a substring in a string using Bash?
EXAMPLE:
I'd like to know how many times this substring...
Bluetooth
Soft blocked: no
Hard blocked: no
...occurs in this string...
0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
NOTE I: I have tried several approaches with sed, grep, awk... Nothing seems to work when we have strings with spaces and multiple lines.
NOTE II: I'm a Linux user and I'm trying a solution that does not involve installing applications/tools outside those that are usually found in Linux distributions.
IMPORTANT:
I would like something like the hypothetical example below. In this case we use two Shell variables (Bash).
EXAMPLE:
STRING="0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no"
SUB_STRING="Bluetooth
Soft blocked: no
Hard blocked: no"
awk -v RS='' 'NR==FNR{str=$0; next} {print gsub(str,"")}' "$STRING" "$SUB_STRING"
NOTE: We are using awk just to illustrate!
bash shell shell-script bash-scripting
add a comment |
How can I count the number of occurrences of a substring in a string using Bash?
EXAMPLE:
I'd like to know how many times this substring...
Bluetooth
Soft blocked: no
Hard blocked: no
...occurs in this string...
0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
NOTE I: I have tried several approaches with sed, grep, awk... Nothing seems to work when we have strings with spaces and multiple lines.
NOTE II: I'm a Linux user and I'm trying a solution that does not involve installing applications/tools outside those that are usually found in Linux distributions.
IMPORTANT:
I would like something like the hypothetical example below. In this case we use two Shell variables (Bash).
EXAMPLE:
STRING="0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no"
SUB_STRING="Bluetooth
Soft blocked: no
Hard blocked: no"
awk -v RS='' 'NR==FNR{str=$0; next} {print gsub(str,"")}' "$STRING" "$SUB_STRING"
NOTE: We are using awk just to illustrate!
bash shell shell-script bash-scripting
You probably will find more help on Stack Overflow, the SE site for programmers. You could also possibly find more help on Unix & Linux SE.
– juniorRubyist
May 7 '18 at 6:06
add a comment |
How can I count the number of occurrences of a substring in a string using Bash?
EXAMPLE:
I'd like to know how many times this substring...
Bluetooth
Soft blocked: no
Hard blocked: no
...occurs in this string...
0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
NOTE I: I have tried several approaches with sed, grep, awk... Nothing seems to work when we have strings with spaces and multiple lines.
NOTE II: I'm a Linux user and I'm trying a solution that does not involve installing applications/tools outside those that are usually found in Linux distributions.
IMPORTANT:
I would like something like the hypothetical example below. In this case we use two Shell variables (Bash).
EXAMPLE:
STRING="0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no"
SUB_STRING="Bluetooth
Soft blocked: no
Hard blocked: no"
awk -v RS='' 'NR==FNR{str=$0; next} {print gsub(str,"")}' "$STRING" "$SUB_STRING"
NOTE: We are using awk just to illustrate!
bash shell shell-script bash-scripting
How can I count the number of occurrences of a substring in a string using Bash?
EXAMPLE:
I'd like to know how many times this substring...
Bluetooth
Soft blocked: no
Hard blocked: no
...occurs in this string...
0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no
NOTE I: I have tried several approaches with sed, grep, awk... Nothing seems to work when we have strings with spaces and multiple lines.
NOTE II: I'm a Linux user and I'm trying a solution that does not involve installing applications/tools outside those that are usually found in Linux distributions.
IMPORTANT:
I would like something like the hypothetical example below. In this case we use two Shell variables (Bash).
EXAMPLE:
STRING="0: asus-wlan: Wireless LAN
Soft blocked: no
Hard blocked: no
1: asus-bluetooth: Bluetooth
Soft blocked: no
Hard blocked: no
2: phy0: Wireless LAN
Soft blocked: no
Hard blocked: no
113: hci0: Bluetooth
Soft blocked: no
Hard blocked: no"
SUB_STRING="Bluetooth
Soft blocked: no
Hard blocked: no"
awk -v RS='' 'NR==FNR{str=$0; next} {print gsub(str,"")}' "$STRING" "$SUB_STRING"
NOTE: We are using awk just to illustrate!
bash shell shell-script bash-scripting
bash shell shell-script bash-scripting
edited May 7 '18 at 16:28
Eduardo Lucio
asked May 7 '18 at 5:03
Eduardo LucioEduardo Lucio
418726
418726
You probably will find more help on Stack Overflow, the SE site for programmers. You could also possibly find more help on Unix & Linux SE.
– juniorRubyist
May 7 '18 at 6:06
add a comment |
You probably will find more help on Stack Overflow, the SE site for programmers. You could also possibly find more help on Unix & Linux SE.
– juniorRubyist
May 7 '18 at 6:06
You probably will find more help on Stack Overflow, the SE site for programmers. You could also possibly find more help on Unix & Linux SE.
– juniorRubyist
May 7 '18 at 6:06
You probably will find more help on Stack Overflow, the SE site for programmers. You could also possibly find more help on Unix & Linux SE.
– juniorRubyist
May 7 '18 at 6:06
add a comment |
2 Answers
2
active
oldest
votes
I assume it can be done better with awk, but this is the best I can offer.
grep -zo "Bluetooths*Soft blocked: nos*Hard blocked: no" file_name | grep -c "Bluetooth"
-z makes grep treat the whole file as one line.
-o only writes the output that matched the string and not the whole line.
(in our case with -z that whould mean the whole file)
s matches blank characters and new lines.
Second instance of grep will search only for the word "Bluetooth" in the output of the first grep call.
-c makes grep write the count of matched regex, instead of the matches themself.
Many thanks @Iskustvo, but I think there is a problem in your answer. We have to escape the string which modifies the amount of spaces and, additionally, we would have to have some functionality to automate this process. Other than that I'd like to be able to use Shell variables (Bash) (see the modification and my question)! I'll try to explain better. For example, AFAIK if my entry is " Soft blocked: no" or "Soft blocked: no" with the value "s*Soft blocked: no" match result becomes indifferent to the spaces of the original string entered. Thanks! =D
– Eduardo Lucio
May 7 '18 at 17:23
2
I understand what you are saying, well, not all of it, but most of it. However I don't think I'm able to provide better answer. Your request exceeds the grep and sed tools and something havier like awk, perl or python will have to be used and I can't help you with that. I hope some other answer will match all your criteria.
– Iskustvo
May 7 '18 at 22:30
Many thanks for your contribution! Sorry for my bad English (actually I speak Portuguese)! =D
– Eduardo Lucio
May 8 '18 at 1:14
add a comment |
It's a bit unclear how you'd like to match (you additional example in the comment above does not shed any light), however assume that you store your string block with the network information inside a file string and the substring block inside a file substring.
Using the following approach, you'd get what I understand you expected: 2 matches.
cat string | tr -s " " | tr 'n' '@' | grep -o "$(cat substring | tr -s " " | tr 'n' '@')" | wc -l
Essentially, both strings are condensed into one line, ignoring whitespaces or tabs, and converting newlines into @. Using the grep -o syntax, we print all the occurrences (-o) of the pattern found.
However, it's unclear if in your example you expect it to match 0 times (exact positional match) or 2 times (ignoring prepended text). This is a very similar solution to what Iskustvo posted here; could it be that we misunderstood your intention?
If you're trying to count matches of a 2-dimensional text fragment, you probably need fuzzy grep.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "3"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1320331%2fbash-count-the-number-of-occurrences-of-a-substring-in-a-string%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I assume it can be done better with awk, but this is the best I can offer.
grep -zo "Bluetooths*Soft blocked: nos*Hard blocked: no" file_name | grep -c "Bluetooth"
-z makes grep treat the whole file as one line.
-o only writes the output that matched the string and not the whole line.
(in our case with -z that whould mean the whole file)
s matches blank characters and new lines.
Second instance of grep will search only for the word "Bluetooth" in the output of the first grep call.
-c makes grep write the count of matched regex, instead of the matches themself.
Many thanks @Iskustvo, but I think there is a problem in your answer. We have to escape the string which modifies the amount of spaces and, additionally, we would have to have some functionality to automate this process. Other than that I'd like to be able to use Shell variables (Bash) (see the modification and my question)! I'll try to explain better. For example, AFAIK if my entry is " Soft blocked: no" or "Soft blocked: no" with the value "s*Soft blocked: no" match result becomes indifferent to the spaces of the original string entered. Thanks! =D
– Eduardo Lucio
May 7 '18 at 17:23
2
I understand what you are saying, well, not all of it, but most of it. However I don't think I'm able to provide better answer. Your request exceeds the grep and sed tools and something havier like awk, perl or python will have to be used and I can't help you with that. I hope some other answer will match all your criteria.
– Iskustvo
May 7 '18 at 22:30
Many thanks for your contribution! Sorry for my bad English (actually I speak Portuguese)! =D
– Eduardo Lucio
May 8 '18 at 1:14
add a comment |
I assume it can be done better with awk, but this is the best I can offer.
grep -zo "Bluetooths*Soft blocked: nos*Hard blocked: no" file_name | grep -c "Bluetooth"
-z makes grep treat the whole file as one line.
-o only writes the output that matched the string and not the whole line.
(in our case with -z that whould mean the whole file)
s matches blank characters and new lines.
Second instance of grep will search only for the word "Bluetooth" in the output of the first grep call.
-c makes grep write the count of matched regex, instead of the matches themself.
Many thanks @Iskustvo, but I think there is a problem in your answer. We have to escape the string which modifies the amount of spaces and, additionally, we would have to have some functionality to automate this process. Other than that I'd like to be able to use Shell variables (Bash) (see the modification and my question)! I'll try to explain better. For example, AFAIK if my entry is " Soft blocked: no" or "Soft blocked: no" with the value "s*Soft blocked: no" match result becomes indifferent to the spaces of the original string entered. Thanks! =D
– Eduardo Lucio
May 7 '18 at 17:23
2
I understand what you are saying, well, not all of it, but most of it. However I don't think I'm able to provide better answer. Your request exceeds the grep and sed tools and something havier like awk, perl or python will have to be used and I can't help you with that. I hope some other answer will match all your criteria.
– Iskustvo
May 7 '18 at 22:30
Many thanks for your contribution! Sorry for my bad English (actually I speak Portuguese)! =D
– Eduardo Lucio
May 8 '18 at 1:14
add a comment |
I assume it can be done better with awk, but this is the best I can offer.
grep -zo "Bluetooths*Soft blocked: nos*Hard blocked: no" file_name | grep -c "Bluetooth"
-z makes grep treat the whole file as one line.
-o only writes the output that matched the string and not the whole line.
(in our case with -z that whould mean the whole file)
s matches blank characters and new lines.
Second instance of grep will search only for the word "Bluetooth" in the output of the first grep call.
-c makes grep write the count of matched regex, instead of the matches themself.
I assume it can be done better with awk, but this is the best I can offer.
grep -zo "Bluetooths*Soft blocked: nos*Hard blocked: no" file_name | grep -c "Bluetooth"
-z makes grep treat the whole file as one line.
-o only writes the output that matched the string and not the whole line.
(in our case with -z that whould mean the whole file)
s matches blank characters and new lines.
Second instance of grep will search only for the word "Bluetooth" in the output of the first grep call.
-c makes grep write the count of matched regex, instead of the matches themself.
answered May 7 '18 at 6:26
IskustvoIskustvo
5712
5712
Many thanks @Iskustvo, but I think there is a problem in your answer. We have to escape the string which modifies the amount of spaces and, additionally, we would have to have some functionality to automate this process. Other than that I'd like to be able to use Shell variables (Bash) (see the modification and my question)! I'll try to explain better. For example, AFAIK if my entry is " Soft blocked: no" or "Soft blocked: no" with the value "s*Soft blocked: no" match result becomes indifferent to the spaces of the original string entered. Thanks! =D
– Eduardo Lucio
May 7 '18 at 17:23
2
I understand what you are saying, well, not all of it, but most of it. However I don't think I'm able to provide better answer. Your request exceeds the grep and sed tools and something havier like awk, perl or python will have to be used and I can't help you with that. I hope some other answer will match all your criteria.
– Iskustvo
May 7 '18 at 22:30
Many thanks for your contribution! Sorry for my bad English (actually I speak Portuguese)! =D
– Eduardo Lucio
May 8 '18 at 1:14
add a comment |
Many thanks @Iskustvo, but I think there is a problem in your answer. We have to escape the string which modifies the amount of spaces and, additionally, we would have to have some functionality to automate this process. Other than that I'd like to be able to use Shell variables (Bash) (see the modification and my question)! I'll try to explain better. For example, AFAIK if my entry is " Soft blocked: no" or "Soft blocked: no" with the value "s*Soft blocked: no" match result becomes indifferent to the spaces of the original string entered. Thanks! =D
– Eduardo Lucio
May 7 '18 at 17:23
2
I understand what you are saying, well, not all of it, but most of it. However I don't think I'm able to provide better answer. Your request exceeds the grep and sed tools and something havier like awk, perl or python will have to be used and I can't help you with that. I hope some other answer will match all your criteria.
– Iskustvo
May 7 '18 at 22:30
Many thanks for your contribution! Sorry for my bad English (actually I speak Portuguese)! =D
– Eduardo Lucio
May 8 '18 at 1:14
Many thanks @Iskustvo, but I think there is a problem in your answer. We have to escape the string which modifies the amount of spaces and, additionally, we would have to have some functionality to automate this process. Other than that I'd like to be able to use Shell variables (Bash) (see the modification and my question)! I'll try to explain better. For example, AFAIK if my entry is " Soft blocked: no" or "Soft blocked: no" with the value "s*Soft blocked: no" match result becomes indifferent to the spaces of the original string entered. Thanks! =D
– Eduardo Lucio
May 7 '18 at 17:23
Many thanks @Iskustvo, but I think there is a problem in your answer. We have to escape the string which modifies the amount of spaces and, additionally, we would have to have some functionality to automate this process. Other than that I'd like to be able to use Shell variables (Bash) (see the modification and my question)! I'll try to explain better. For example, AFAIK if my entry is " Soft blocked: no" or "Soft blocked: no" with the value "s*Soft blocked: no" match result becomes indifferent to the spaces of the original string entered. Thanks! =D
– Eduardo Lucio
May 7 '18 at 17:23
2
2
I understand what you are saying, well, not all of it, but most of it. However I don't think I'm able to provide better answer. Your request exceeds the grep and sed tools and something havier like awk, perl or python will have to be used and I can't help you with that. I hope some other answer will match all your criteria.
– Iskustvo
May 7 '18 at 22:30
I understand what you are saying, well, not all of it, but most of it. However I don't think I'm able to provide better answer. Your request exceeds the grep and sed tools and something havier like awk, perl or python will have to be used and I can't help you with that. I hope some other answer will match all your criteria.
– Iskustvo
May 7 '18 at 22:30
Many thanks for your contribution! Sorry for my bad English (actually I speak Portuguese)! =D
– Eduardo Lucio
May 8 '18 at 1:14
Many thanks for your contribution! Sorry for my bad English (actually I speak Portuguese)! =D
– Eduardo Lucio
May 8 '18 at 1:14
add a comment |
It's a bit unclear how you'd like to match (you additional example in the comment above does not shed any light), however assume that you store your string block with the network information inside a file string and the substring block inside a file substring.
Using the following approach, you'd get what I understand you expected: 2 matches.
cat string | tr -s " " | tr 'n' '@' | grep -o "$(cat substring | tr -s " " | tr 'n' '@')" | wc -l
Essentially, both strings are condensed into one line, ignoring whitespaces or tabs, and converting newlines into @. Using the grep -o syntax, we print all the occurrences (-o) of the pattern found.
However, it's unclear if in your example you expect it to match 0 times (exact positional match) or 2 times (ignoring prepended text). This is a very similar solution to what Iskustvo posted here; could it be that we misunderstood your intention?
If you're trying to count matches of a 2-dimensional text fragment, you probably need fuzzy grep.
add a comment |
It's a bit unclear how you'd like to match (you additional example in the comment above does not shed any light), however assume that you store your string block with the network information inside a file string and the substring block inside a file substring.
Using the following approach, you'd get what I understand you expected: 2 matches.
cat string | tr -s " " | tr 'n' '@' | grep -o "$(cat substring | tr -s " " | tr 'n' '@')" | wc -l
Essentially, both strings are condensed into one line, ignoring whitespaces or tabs, and converting newlines into @. Using the grep -o syntax, we print all the occurrences (-o) of the pattern found.
However, it's unclear if in your example you expect it to match 0 times (exact positional match) or 2 times (ignoring prepended text). This is a very similar solution to what Iskustvo posted here; could it be that we misunderstood your intention?
If you're trying to count matches of a 2-dimensional text fragment, you probably need fuzzy grep.
add a comment |
It's a bit unclear how you'd like to match (you additional example in the comment above does not shed any light), however assume that you store your string block with the network information inside a file string and the substring block inside a file substring.
Using the following approach, you'd get what I understand you expected: 2 matches.
cat string | tr -s " " | tr 'n' '@' | grep -o "$(cat substring | tr -s " " | tr 'n' '@')" | wc -l
Essentially, both strings are condensed into one line, ignoring whitespaces or tabs, and converting newlines into @. Using the grep -o syntax, we print all the occurrences (-o) of the pattern found.
However, it's unclear if in your example you expect it to match 0 times (exact positional match) or 2 times (ignoring prepended text). This is a very similar solution to what Iskustvo posted here; could it be that we misunderstood your intention?
If you're trying to count matches of a 2-dimensional text fragment, you probably need fuzzy grep.
It's a bit unclear how you'd like to match (you additional example in the comment above does not shed any light), however assume that you store your string block with the network information inside a file string and the substring block inside a file substring.
Using the following approach, you'd get what I understand you expected: 2 matches.
cat string | tr -s " " | tr 'n' '@' | grep -o "$(cat substring | tr -s " " | tr 'n' '@')" | wc -l
Essentially, both strings are condensed into one line, ignoring whitespaces or tabs, and converting newlines into @. Using the grep -o syntax, we print all the occurrences (-o) of the pattern found.
However, it's unclear if in your example you expect it to match 0 times (exact positional match) or 2 times (ignoring prepended text). This is a very similar solution to what Iskustvo posted here; could it be that we misunderstood your intention?
If you're trying to count matches of a 2-dimensional text fragment, you probably need fuzzy grep.
answered Feb 4 at 23:02
MoreakiMoreaki
546614
546614
add a comment |
add a comment |
Thanks for contributing an answer to Super User!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsuperuser.com%2fquestions%2f1320331%2fbash-count-the-number-of-occurrences-of-a-substring-in-a-string%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You probably will find more help on Stack Overflow, the SE site for programmers. You could also possibly find more help on Unix & Linux SE.
– juniorRubyist
May 7 '18 at 6:06