Como posso contar o número de ocorrências de uma substring em uma string usando o Bash?
EXEMPLO:
Eu gostaria de saber quantas vezes esta substring:
Bluetooth
Soft blocked: no
Hard blocked: no
...ocorre nesta 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
NOTA I: Eu tentei várias abordagens com sed, grep, awk... Nada parece funcionar quando temos strings com espaços e múltiplas linhas.
NOTA II: Sou usuário Linux e estou tentando uma solução que não envolva a instalação de aplicativos/ferramentas fora daquelas que normalmente são encontradas nas distribuições Linux.
IMPORTANTE:
Eu gostaria de algo como o exemplo hipotético abaixo. Neste caso usamos duas variáveis Shell (Bash) .
EXEMPLO:
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='\0' 'NR==FNR{str=$0; next} {print gsub(str,"")}' "$STRING" "$SUB_STRING"
NOTA: Estamos usando o awk apenas para ilustrar!
Com
perl
:Com
bash
sozinho, você sempre pode fazer algo como:Isso
$s
contém$STRING
com todas as ocorrências de$SUB_STRING
dentro dele removidas. Descobrimos o número de$SUB_STRING
s que foram removidos calculando a diferença no número de caracteres entre$STRING
e$s
e dividindo pelo comprimento de$SUB_STRING
si mesmo.POSIXLY, você poderia fazer algo como:
Usando funções de processamento de strings, poderíamos fazer isso com Perl da seguinte forma:
Explicação:
Alguns outros métodos estão listados abaixo:
Slurp a string e use regex.
° Slurp string na variável $_.
° passar a substring da linha de comando para perl usando a opção -s.
° agora realiza uma correspondência em $ _ e em um contexto de lista obtém as correspondências que são então obtidas no contexto escalar para obter o número de correspondências.
° a opção -p imprime automaticamente o que está em $_.
Método usando a ferramenta sed :
° Como etapa preparatória, vamos em frente e escapamos todos os caracteres que atuam como metacaracteres para o lado esquerdo da instrução s/// na substring que, se não for feito, fará com que o sed trave.
° Agora colocamos toda a corda no espaço do padrão.
° então continuamos imprimindo uma linha vazia, o hold space é um bom candidato, e retiramos a substring do pattern space.
° enxágue... ensaboe... repita enquanto a substring estiver presente.
° as linhas vazias são então canalizadas para a ferramenta wc, que nos dará a contagem de linhas = número de vezes que a substring foi encontrada.
Esta é a versão do shell:
Se a substring não contiver quebras de linha:
Você pode usar o Python como nesta pergunta
Ou se você estiver trabalhando com variáveis de shell:
No seu caso:
Explicação
RS
- o separador de registro de entrada, por padrão, uma nova linha. Defina-o como a string necessária eawk
dividirá todo o texto em registros, usando essa string como separador. Então, resta apenas imprimir o número de registros subtraídos por1
naEND
seção.Usando variáveis:
Se você tiver o gnugrep, poderá executar algo nas linhas de
grep -zPio 'Bluetooth\s+Soft blocked: no\s+Hard blocked: no' ex.txt | grep -zc .