2017-02-21 16 views
0

Я пытаюсь найти местоположение всех экземпляров строки в определенном файле; однако код, который я сейчас выполняю, возвращает только местоположение первого экземпляра, а затем останавливается. Вот что я в настоящее время работает:Поиск расположения символов всех экземпляров строки в bash

str=$(cat temp1.txt) 
tmp="${str%%<C>*}" 

if [ "$tmp" != "$str" ]; then 
echo ${#tmp} 
fi 

Файл только одна строка строки, и я бы отобразить его, но вопросы формата должны быть не позволит мне добавить нужное количество пробелов между каждый знак.

+1

Пример ввода и ожидаемого выхода, пожалуйста. – chepner

+0

Я попытался представить образец ввода, но форматирование вопроса не позволяет применить правильное количество интервалов между символами. Это по существу одна строка, содержащая несколько раз с различными количествами пробелов между ними. Мне просто нужно место каждого события. – Zach

ответ

1

Я не уверен, что многие детали ваших требований, однако это awk один вкладыш:

awk -vRS='<C>' '{printf("%u:",a+=length($0));a+=length(RS)}END{print ""}' temp1.txt 

Давайте протестируем его с фактической линии ввода:

$ awk -vRS='<C>' \ 
    '{printf("%u:",a+=length($0));a+=length(RS)}END{print ""}' \ 
    <<<" <C>  <C> " 
4:14:20: 

Это означает, : первый <C> находится в байте 4, второй <C> находится в байте 14 (включая три байта первого <C>), а вся строка длиной 20 байтов (включая окончательную новую строку).

Это то, что вы хотите?

Объяснение

Мы установили (-v) разделитель записей (RS) в качестве <C>. Затем мы сохраняем переменную a с подсчетом всех обработанных байтов. Для каждой «линии» (т. Е. <C> - разделенных подстрок) мы добавляем длину текущей строки в a, printf ее подходящим форматом "%u:" и увеличиваем a на длину разделителя, которая закончила текущую линию. Так как никакая печать пока не включала новые строки, на END мы получаем print пустую строку, которая является идиомой для вывода окончательной новой строки.

+0

Я запустил это, и мой компьютер, похоже, отклонил разделитель записи -v: «awk: invalid -v option» – Zach

+0

Не обращайте внимания, была опечатка, и это сработало! Спасибо огромное! – Zach

0

Посмотрите в основном на тот же вопрос here.

В частности, на ваш вопрос может быть дан ответ для нескольких экземпляров благодаря пользователю JRFerguson ответ с использованием perl.

EDIT: Я нашел другое решение, которое может просто сделать трюк here. (. Главный вопрос и ответ пост найден here)

Я изменил оболочку из KSH на баш, изменил искомую строку включать в себя несколько <C> «S, чтобы лучше продемонстрировать ответ на этот вопрос, и назвал его„тестер“:

#!/bin/bash 
printf '%s\n' '<C>abc<C>xyz<C>123456<C>zzz<C>' | awk -v s="$1" ' 
{  d = "" 
     for(i = 1; x = index(substr($0, i), s); i = i + x + length(s) - 1) { 
       printf("%s%d", d, i + x - 1) 
       d = ":" 
     } 
     print "" 
}' 

Это, как я побежал:

$ tester '<C>' 
1:7:13:22:28 

Я не понял код из (я хотел бы знать, почему это работает), но это, кажется, работает! Было бы неплохо получить объяснение и изящный способ подачи строки в этот скрипт. Приветствия.

+0

Я действительно использовал этот вопрос, чтобы написать свою первую попытку этого кода. Он возвращает только первое вхождение строки, которую я ищу. – Zach