Как найти строку с окончанием слова

Требуется найти конец строки, если в ней содержится заданное слово.
Конец строки и слово могут разделяться неизвестным количеством символов.
Поиск конца строки: $
Поиск места, перед которым есть заданное слово: (?<=word)
Как добавить пропуск всего до конца строки, не могу сообразить. Если пишу (?<=word.*)$, то вхождений не находится.


  • Вопрос задан

    более трёх лет назад

  • 270 просмотров

Поиск подстроки

Последнее обновление: 02.03.2023

Функция find() возвращает индекс первого вхождения подстроки или отдельного символа в строке в виде значние я типа size_t:

#include <iostream>
#include <string>

int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::cout << text.find("ed") << std::endl;      // 14
    std::cout << text.find("friend") << std::endl;  // 2
    std::cout << text.find('d') << std::endl;     // 7
    std::cout << text.find("apple") << std::endl;  // 18446744073709551615
}

Если строка или символ не найдены (как в примере выше в последнем случае), то возвращается специальная константа std::string::npos,
которая представляет очень большое число (как видно из примера, число 18446744073709551615). И при поиске мы можем проверять результат функции find() на равенство этой константе:

if (text.find("banana") == std::string::npos)
{
    std::cout << "Not found" << std::endl;
}

Функция find имеет ряд дополнительных версий. Так, с помощью второго параметра мы можем указать индекс, с которого надо вести поиск:

#include <iostream>
#include <string>

int main()
{
    std::string text {"A friend in need is a friend indeed."};
    // поиск с 10-го индекса
    std::cout << text.find("friend", 10) << std::endl;      // 22
}

Используя эту версию, мы можем написать программу для поиска количества вхождений строки в тексте, то есть выяснить, сколько раз строка встречается в тексте:

#include <iostream>
#include <string>

int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::string word {"friend"};
    unsigned count{};       // количество вхождений
    for (unsigned i {}; i <= text.length() - word.length(); )
    {
        // получаем индекс
        size_t position = text.find(word, i);
        // если не найдено ни одного вхождения с индекса i, выходим из цикла
        if (position == std::string::npos) break;
        // если же вхождение найдено, увеличиваем счетчик вхождений
        ++count;
        // переходим к следующему индексу после position
        i = position + 1;
    }
    std::cout << "The word is found " << count << " times." << std::endl; // The word is found 2 times.
}

Здесь в цикле пробегаемся по тексту, в котором надо найти строку, пока счетчик i не будет равен text.length() - word.length().
С помощью функции find() получаем индекс первого вхождения слова в тексте, начиная с индекса i. Если таких вхождений не найдено, то выходим из цикла.
Если же найден индекс, то счетчик i получает индекс, следующий за индексом найденного вхождения.

В итоге, поскольку искомое слово «friend» встречается в тексте два раза, то программа выведет

The word is found 2 times.

В качестве альтернативы мы могли бы использовать цикл while:

#include <iostream>
#include <string>

int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::string word {"friend"};
    unsigned count{};       // количество вхождений
    size_t index{}; // начальный индекс
    while ((index = text.find(word, index)) != std::string::npos)
    {
        ++count;
        index += word.length(); // перемещаем индекс на позицию после завершения слова в тексте
    }
    std::cout << "The word is found " << count << " times." << std::endl;
}

Еще одна версия позволяет искать в тексте не всю строку, а только ее часть. Для этого в качестве третьего параметра передается количество символов из искомой строки, которые программа будет искать в тексте:

#include <iostream>
#include <string>

int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::string word {"endless"};
    // поиск с 10-го индекса 3 первых символов слова "endless", то есть "end"
    std::cout << text.find("endless", 10, 3) << std::endl;      // 25
}

Стоит отметить, что в этом случае искомая строка должна представлять строковый литерал или строку в С-стиле (например, символьный массив с концевым нулевым байтом).

Функция rfind. Поиск в обратном порядке

Функция rfind() работает аналогично функции find(), принимает те же самые параметры, только ищет подстроку в обратном порядке — с конца строки:

#include <iostream>
#include <string>

int main()
{
    std::string text {"A friend in need is a friend indeed."};
    std::cout << text.rfind("ed") << std::endl;      // 33
    std::cout << text.rfind("friend") << std::endl; // 22
    std::cout << text.rfind('d') << std::endl;     // 34
    std::cout << text.rfind("apple") << std::endl;  // 18446744073709551615
}

Поиск любого из набора символов

Пара функций — find_first_of() и find_last_of() позволяют найти соответственно первый и последний индекс любого из набора символов:

#include <iostream>
#include <string>

int main()
{
    std::string text {"Phone number: +23415678901"};
    std::string letters{"0123456789"};  // искомые символы
    std::cout << text.find_first_of(letters) << std::endl;      // 15
    std::cout << text.find_last_of(letters) << std::endl;      // 25
}

В данном случае ищем в строке «Phone number: +23415678901» первую и последнюю позицию любого из символов из строки «0123456789». То есть таким образом мы найдем начальный и конечный индекс
номера телефона.

Если нам, наоборот, надо найти позиции символов, которые НЕ представляют любой символ из набора, то мы можем использовать функции find_first_not_of() (первая позиция)
и find_last_not_of() (последняя позиция):

#include <iostream>
#include <string>

int main()
{
    std::string text {"Phone number: +23415678901"};
    std::string letters{"0123456789"};  // искомые символы
    std::cout << text.find_first_not_of(letters) << std::endl;      // 0
    std::cout << text.find_last_not_of(letters) << std::endl;      // 14
}

Мы можем комбинировать функции. Например, найдем количество слов в строке:

#include <iostream>
#include <string>

int main()
{
    std::string text {"When in Rome, do as the Romans do."};    // исходный текст
    const std::string separators{ " ,;:."!?'*n" }; // разделители слов
    unsigned count{};   // счетчик слов
    size_t start { text.find_first_not_of(separators) }; // начальный индекс первого слова
    while (start != std::string::npos) // если нашли слово
    {
        // увеличиваем счетчик слов
        count++;
        size_t end = text.find_first_of(separators, start + 1); // находим, где кончается слово
        if (end == std::string::npos) 
        {
            end = text.length();
        }
        start = text.find_first_not_of(separators, end + 1); // находим начальный индекс следующего слова и переустанавливаем start
    }
    // выводим количество слов
    std::cout << "Text contains " << count << " words" << std::endl;    // Text contains 8 words
}

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

const std::string separators{ " ,;:."!?'*n" }; // разделители слов

Перед обработкой введенного текста фиксируем индекс первого символа первого слова в тексте. Для этого применяется функция find_first_not_of(), которая возвращает
первый индекс любого символа, который не входит в строку separators:

size_t start { text.find_first_not_of(separators) };

Далее в цикле while смотрим, является ли полученный индекс действительным индексом:

while (start != std::string::npos)

Например, если в строке одни только символы из набора separators, тогда функция find_first_not_of() возвратит значение std::string::npos,
что будет означать, что в тексте больше нет непунктационных знаков.

И если start указывает на действительный индекс начала слова, то увеличиваем счетчик слово. Далее находим индекс первого символа из separators, который идет сразу после слова. То есть фактически это индекс после
последнего символа слова, который помещаем в переменную end:

size_t end = text.find_first_of(separators, start + 1); // находим, где закончилось слово

Для нахождения позиции окончания слова используем функцию find_first_of(), которая возвращает первую позицию любого символа из separators, начиная с индекса start+1

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

if (end == std::string::npos) // если НЕ найден ни один из символов-разделителей
    end = text.length();        // устанавливаем переменную end на конец текста

После того, как мы нашли начальный индексы слова и его конец, переустанавливаем start на начальный индекс следующего слова и повторяем действия цикла:

start = text.find_first_not_of(separators, end + 1); // находим начальный индекс следующего слова и переустанавливаем start

В конце выводим количество найденных слов.

Я получаю адрес ввода в виде одной длинной строки, в отличие от имени, адреса, города, штата и почтового индекса. Я разделил большую часть этого, кроме того, между адресом и городом. Поэтому я хочу найти любое название улицы (двор, улица, улица, проспект и т. Д.), А затем разбить строку в конце слова. Тогда я останусь с адресом и городом отдельно.

strpos() только дает мне позицию начало ключевого слова, я хочу разделить его на конец ключевого слова.
Например, вот где я до:

John Doe
1 Main Street Anytown
NY
00000

Я хочу разделить между Street а также Anytown, И этот адрес не будет статичным, может быть больше слов и т. Д.

Другая идея — функция, которая автоматически разбивает строку на разные поля. Кто-то сказал мне, что в некоторых странах у почтовой службы есть API, который это делает. У USPS есть такая вещь? Их сайт не указывает на это.

1

Решение

На самом деле, вам нужно найти несколько игл в стоге сена, суммировать положение и длину иглы.

function strpos_street($string){
$types = [
'court',
'road',
'street',
'avenue'
];
foreach($types as $t){
$pos = strpos(strtolower($string), strtolower($t));
if($pos === false) continue;
else return $pos + strlen($t) - 1;
}
return -1;
}

echo strpos_street($string);

Некоторые советы:

  • Учитывайте чувствительность к регистру
  • Вы можете использовать explode функционировать таким же итерационным способом
  • Я не уверен, но могут быть некоторые адреса, которые содержат и слова «улица» и «улица»

1

Другие решения

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

$str = '1 Main Street Anytown';
$array_of_string = explode('street',$str);

затем $array_of_strings[0] воля содержит 1 Main а также $array_of_strings[1] воля содержит Anytown

1

Вы могли бы сделать что-то вроде этого.

$word = "Street"
$pos = strpos($word, $address);
if ($pos !== false) {
$pos += strlen($word) - 1;
...
}

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

0

Кажется, что вы пытаетесь искать в обратном направлении, как strpos по умолчанию задает положение строки, начиная с начала, вам нужно установить смещение -1 и вычесть из strlen.

то есть

strlen($address) - strpos($address, 'Anytown', -1) - 1;
//search from reverse and output position starting from reverse

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

0

Сам не так давно начал питон, немного не понимаю почему он не ищет мне слова и вообще ничего не выводит.

Задание такое: Дан набор слов, разделенных точкой с запятой (;). Набор заканчивается двоеточием (:). Определить, сколько в нем слов, заканчивающихся буквой а.

Мой код, помогите доделать до конца)

string = "Добро;Зло;Земля;Игра;Машина:"
i = 0
k = 0
while i == 1:
    len(string) - 1
    if string[i]== "а" and string[i+1] == ";" or string[i+1] == ":":
        k=k+1
        print(k)

Вроде уже лучше стало, но результат не совсем правильный вроде

string = "Добро;Зло;Земля;Игра;Машина;Куша:"
i = 0
k = 0
for i in range(len(string)-1):
    if string[i] == "а" and string[i+1] == ";" or string[i+1] == ":":
        k = k+1

print(k)

    Содержание:

  • Mетасимволы и их значение
  • Примеры применения метасимволов для поиска
  • Примеры применения регулярных выражений для поиска и замены
  • Как очистить историю «поиска» в Notepad++

Регулярное выражение – это шаблон текста, который состоит из обычных символов (например, букв от а до я) и специальных символов, известных как метасимволы. Шаблон задает правила поиска и может осуществлять различные манипуляции с текстом.

Далее приведены метасимволы и их значение, а затем уже примеры применения.

Mетасимволы и их значение

Mетасимволы и их значение

Символ Описание
. Точка представляет один любой символ
^ Начало строки
$ Конец строки
^$ Пустая строка (начало и конец, между которыми пусто)
.+ Любая не пустая строка
s Пробел
S Не Пробел
w Буква, цифра или подчеркивание
d Любая цифра
D Любой символ, но не цифра
[0-9] Любая цифра
[a-z] Любая буква от a до z (латинский набор символов) в нижнем регистре 1
[а-я] Любая буква от a до я (русский набор символов) в нижнем регистре 1
[A-Z] Любая буква от a до z в ВЕРХНЕМ регистре 1
[А-Я] Любая буква от А до Я в ВЕРХНЕМ регистре 1
* «Повторитель». Означает, что предшествующий символ может повторяться (0 или более раз)
.* Абсолютно любой набор символов. Например, условие <p>.*</p> найдет любой текст между тегами <p> </p>
(^.*$) Любой текст между началом и концом строки

Примеры применения метасимволов для поиска

Примеры применения метасимволов для поиска

Пример Описание
([0-9][0-9]*.) ищет любые цифры, в данном случае двухзначные цифры
n ищет символ новой строки
r ищет пустые строки содержащий символы «перевод каретки»
^$ ищет пустые строки
nr ищет пустые строки содержащий символы – символ новой строки и «перевод каретки»
s ищет класс пробельных символов. К пробельным символам относятся пробел, символ табуляции, возврат каретки, символ новой строки и символ перевода страницы. То же самое, что и [ t,r,n,f]
S ищет класс не пробельных символов. То же самое, что и [^ t,r,n,f]
^s*$ ищет пустые строки содержащие пробел 2
^[ ]*$ ищет пустые строки содержащие пробел 2
^Тест ищет слово Тест в начале строки
Тест$ ищет слово Тест в конце строки
bтом ищет набор символов том только в начале слов, то есть в слове Томск будет найдено, а в слове Потом нет
томb ищет набор символов том только в конце слов, то есть в слове Томск не будет найдено, а в слове Потом будет
BтомB ищет набор символов том не в начале и не в конце слов, то есть в слове Томск не будет найдено, и слово Потом также будет проигнорировано, а вот в словах Автоматизация, Хрестоматия будет найдено
Маша|Оля ищет все заданные слова в тексте. Например, нужно найти определенные имена в тесте — Маша и Оля, вечером собирались в кино, но встретив Сашу и Пашу, Маша ушла с Пашей на концерт, а Оля с Сашей решили погулять в парке. Найдет все слова Маша и Оля, то есть четыре совпадения.

1, 2 Часть примеров уже устарела, notepad++ совершенствуется и часть примеров делается стандартными командами. Например, конструкции вида [а-яА-Я]искать в любом из регистров потеряли смысл, а явное указание на регистр при снятом чек-боксе будет проигнорировано и будут найдены все вхождения в верхнем и нижнем регистрах.

«Удалить пустые строки содержащие пробел» сейчас выполняется через меню «Правка» – «Операции со строками». Но с их помощью можно разрабатывать свои шаблоны поиска и замены.

Примеры применения регулярных выражений для поиска и замены

Поиск и замена с помощью регулярных выражений в notepad++

Рисунок 1. Графическое изображение примера поиска поиска и замены абзаца

Важное отступление

Если в шаблоне поиска («Найти») встречаются символы схожие с метасимволами, то их нужно экранировать квадратными скобками. Например, в искомом тексте нужно найти именно вот такое сочетание 123*456, то есть в нём есть символ *, тогда в поле «Найти» должно быть 123[*]456. В противном случае, будет искаться сочетание вида 1233456, так как * означает повторитель.

В примере «Поиск фразы только в середине текста», точка в в ред. Федерального закона не экранирована, так как в данном случае не принципиально будет искаться именно точка или любой другой символ.
Если предположить, что в тексте могут быть фразы вроде — в ред: Федерального закона и такие фразы нужно не учитывать при поиске, то тогда, точку следует указать явно —
^.* в ред[.] Федерального закона .*$.



Пример 1

Находит новую строку и добавляет к ней пустую строку найти: (^.*$) заменить: 1nr


Находит конец строки и добавляет к ней тег <br>
найти:
$
заменить:
<br>1

Находит новую строку и заключает её в теги абзаца <p></p>
найти:
(^.*$)
заменить:
<p>1</p>

Находит новую строку и заключает её в теги списка <li></li>
найти:
(^.*$)
заменить:
<li>1</li>

Поиск фразы только в середине текста3
Найти в тексте строки в которых может быть любой текст как до начала 
фразы в ред. Федерального закона, так и после этой фразы до конца строки
найти:
^.* в ред. Федерального закона .*$

3 Пример может сначала показаться лишенным смысла, так как эти же самые условия можно получить просто указав в ред. Федерального закона, однако возможно вам необходимо:

  • чтобы поиск не учитывал фразу в ред. Федерального закона, если именно с неё начинается строка;
  • чтобы поиск не учитывал фразу в ред. Федерального закона, если именно ей оканчивается строка;
  • вы собираетесь до и после искомой фразы добавить что-то такое эдакое, например начало новой строки, чтобы в дальнейшем заменить её ещё на что-либо.

В этих случаях, простой поиск уже не сработает. Хотя возможно это выражение можно сократить или как то усовершенствовать.

Удалить все предложения, в которых стоит запятая после первого слова

Необходимо удалить все предложения, в которых стоит запятая после первого слова в этом предложении.



Пример 2

1. Во вкладке поиска «Пометки» устанавливаем чек-бокс «помечать закладкой» (Рисунок 2) 2. В поле найти добавляем: (^[а-я]*,) 3. После выставления в тексте пометок, выполняем команду: «Меню/Поиск/Закладки/Удалить все строки С закладкой»

Поиск и замена с помощью регулярных выражений в notepad++

Рисунок 2. Удалить все предложения, в которых стоит запятая после первого слова

Как очистить историю «поиска» в Notepad++

Давно пользуюсь «поиском и заменой», и столько же меня раздражала одна маленькая особенность, с которой я мирился до поры до времени.

А именно, то, что редактор ведет историю «поиска и замены», и при следующем поиске – автоматически предлагает ей (историей) воспользоваться , что безусловно очень удобно в рамках правки одного документа. Все заготовки как говорится «под рукой», не нужно ничего вводить заново.

Однако не всегда это является плюсом, порой после этот список весьма обширен, но уже совершенно не нужен и лишь отвлекает. Раньше старался просто не обращать внимания на эти мелкие неудобства.

Как очистить историю «поиска» в Notepad++

рисунок 3

Недавно узнал как очистить список истории «поиска и замены», не скажу что этот способ очень быстрый и удобный, но может быть кому-то пригодится.

Вернее он кажется долгим, так как нужно идти в скрытый каталог, там что искать. Однако если где-нибудь сохранить путь к файлу, то процесс этот занимает секунд 30 примерно.

Важно!
Нижеперечисленные действия нужно выполнять в любом другом редакторе, но не в Notepad++, можно в системном блокноте.

  1. Закрываем notepad++;
  2. Открываем файл config.xml (%User%Application DataRoamingNotepad++config.xml) или как-то так …

    У меня полный путь выглядит так — C:UsersUserAppDataRoamingNotepad++config.xml, здесь все зависит от вашей ОС, а также от способа установки Notepad++, может быть файл где сохраняется история находится непосредственно в директории программы;

  3. Удаляем всё что между тегами <FindHistory></FindHistory> – рисунок 4.
  4. Сохраняем изменения, закрываем блокнот;
  5. Открываем notepad++ без истории.

Как очистить историю «поиска» в Notepad++

рисунок 4

Понравилась статья? Поделить с друзьями:
  • Как составить бриф для разработки сайта
  • Продуктивность транспирации как найти
  • Как найти приложение в контакте для айфона
  • Как найти штаны по фотке
  • Как найти мужчину стихи красивые