Encontrando strings múltiplas posições em um arquivo de texto grande

1

Eu preciso encontrar as posições exatas dentro do texto de uma certa string. isto é Arquivo:

to be or not to be, that's the question

String "para". Saída necessária: 0,14 (caracteres desde o começo até encontrar minha picada). Eu tentei:

$ grep -o 'to' myfile.txt | wc -l

isso me dá "8597", ... Eu assumo que este é o número total, mas eu preciso das posições dentro do texto, em caracteres.

    
por Jose 01.08.2018 / 09:16

4 respostas

1

$ awk -v str='to' '{ off=0; while (pos=index(substr($0,off+1),str)) { printf("%d: %d\n", NR, pos+off); off+=length(str)+pos } }' file
1: 1
1: 14

Ou mais bem formatado:

awk -v str='to' '
    {
        off = 0  # current offset in the line from whence we are searching
        while (pos = index(substr($0, off + 1), str)) {
            # pos is the position within the substring where the string was found
            printf("%d: %d\n", NR, pos + off)
            off += length(str) + pos
        }
    }' file

O programa awk exibe o número da linha seguido pela posição da string nessa linha. Se a string ocorrer várias vezes na linha, várias linhas de saída serão produzidas.

O programa usa a função index() para encontrar a string na linha e, se for encontrada, imprime a posição na linha onde é encontrada. Em seguida, ele repete o processo para o restante da linha (usando a função substr() ) até que nenhuma instância da cadeia seja encontrada.

No código, a variável off mantém o controle do deslocamento desde o início da linha a partir da qual precisamos fazer a próxima pesquisa. A variável pso contém a posição dentro da substring no deslocamento off onde a string foi encontrada.

A string é passada na linha de comando usando -v str='to' .

Exemplo:

$ cat file
To be, or not to be: that is the question:
Whether ‘tis nobler in the mind to suffer
The slings and arrows of outrageous fortune,
Or to take arms against a sea of troubles,
And by opposing end them? To die: to sleep;
No more; and by a sleep to say we end
The heart-ache and the thousand natural shocks
That flesh is heir to, ‘tis a consummation
Devoutly to be wish’d. To die, to sleep;

$ awk -v str='the' '{ off=0; while (pos=index(substr($0,off+1), str)) { printf("%d: %d\n", NR, pos+off); off+=length(str)+pos} }' file
1: 30
2: 4
2: 26
5: 21
7: 20
    
por 01.08.2018 / 09:45
1

se o seu arquivo tiver várias linhas, para encontrar a primeira ocorrência da sua string, você pode usar:

sed -zE 's/^(\w[^to]+)(to)(.*)//' YourFile | wc -c
    
por 01.08.2018 / 11:26
0

Tente

grep -b 'to' file

para deslocamento desde o começo do arquivo; ou

grep -nb 'to' file

para o número da linha e o deslocamento.

    
por 01.08.2018 / 10:04
0

Você pode usar grep para fazer isso:

$ grep -aob 'to' file | grep -oE '[0-9]+'
0
13

Aliás, sua matemática aparece quando você diz que está procurando por 0,14, o segundo to começa na posição 13, se você está contando 0 como o primeiro, com o qual você parece ter suas coordenadas iniciadas com 0.

Se você quiser que a saída acima seja uma lista de coordenadas separadas por vírgulas:

$ grep -aob 'to' file | grep -oE '[0-9]+' | paste -s -d ','
0,13

Como isso funciona?

Este método explora a capacidade do GNU grep de imprimir o byte offset de correspondências ( -b ), e nós o forçamos a imprimi-las somente através da opção -o .

   -b, --byte-offset
          Print the 0-based byte offset within the input file before each
          line of output.  If -o (--only-matching) is specified, print the 
          offset of the matching part itself.

Exemplos mais avançados

Se o seu exemplo incluísse palavras como toto ou fosse multilinha, essa versão aprimorada da abordagem acima também poderia lidar com isso.

Dados de amostra
$ cat file
to be or not to be, that's the question
that is the to to question
toto is a dog
Exemplo
$ grep -aob '\bto\b' file | grep -oE '[0-9]+' | paste -s -d ','
0,13,52,55

Aqui estamos usando limites de palavras \b em ambos os lados da palavra que estamos contando para contar apenas ocorrências explícitas da string to e não palavras como toto .

Referências

por 01.08.2018 / 10:45

Tags