Нахождение строки нескольких позиций в большом текстовом файле

Gnu parallel позволит вам запускать несколько процессов из shell-скрипта параллельно, ожидая их завершения.

1
01.08.2018, 11:28
4 ответа
$ 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

Или в более красивом формате:

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

Программа awkвыводит номер строки, за которым следует позиция строки в этой строке. Если строка встречается в строке несколько раз, будет создано несколько строк вывода.

Программа использует функцию index()для поиска строки в строке и, если она найдена, выводит позицию в строке, где она найдена. Затем процесс повторяется для остальной части строки (с использованием функции substr())до тех пор, пока не будет найдено больше экземпляров строки.

В коде переменная offотслеживает смещение от начала строки, с которой нам нужно выполнить следующий поиск. Переменная psoсодержит позицию внутри подстроки по смещению off, где была найдена строка.

Строка передается в командной строке с помощью -v str='to'.

Пример:

$ 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
1
27.01.2020, 23:31

Попробуйте

grep -b 'to' file

для смещения от начала файла; или

grep -nb 'to' file

для номера строки и смещения.

1
27.01.2020, 23:31

Для этого можно использовать grep:

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

Между прочим, ваша математика выходит из строя, когда вы заявляете, что ищете 0,14, 2-й toначинается с позиции 13, если вы считаете 0 первым, что, по-видимому, дает ваши координаты, начинающиеся с 0.

Если вы хотите, чтобы приведенный выше вывод представлял собой список координат, разделенных запятыми:

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

Как это работает?

Этот метод использует способность GNU grepпечатать смещение совпадений в байтах (-b), и мы заставляем его печатать их только с помощью переключателя -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.

Дополнительные примеры

Если ваш пример должен включать такие слова, как totoили многострочные -строки, эта улучшенная версия описанного выше подхода также может обрабатывать их.

Пример данных
$ cat file
to be or not to be, that's the question
that is the to to question
toto is a dog
Пример
$ grep -aob '\bto\b' file | grep -oE '[0-9]+' | paste -s -d ','
0,13,52,55

Здесь мы используем границы слов \bпо обе стороны от слова, которое мы подсчитываем, чтобы подсчитывать только явные вхождения строки to, а не такие слова, как toto.

Ссылки

0
27.01.2020, 23:31

если ваш файл состоит из нескольких строк, чтобы найти первое вхождение вашей строки, вы можете использовать:

sed -zE 's/^(\w[^to]+)(to)(.*)/\1\2/' YourFile | wc -c
1
27.01.2020, 23:31

Теги

Похожие вопросы