Как подсчитать количество вхождений подстроки в строку, используя Bash?

ПРИМЕР:

Я хотел бы знать, сколько раз эта подстрока ...

Bluetooth
         Soft blocked: no
         Hard blocked: no

... происходит в этой строке ...

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

ПРИМЕЧАНИЕ I: я пробовал несколько подходов с помощью sed, grep, awk ... Ничто, кажется, не работает, когда у нас есть строки с пробелами и несколькими строками.

ПРИМЕЧАНИЕ II: я пользователь Linux и пытаюсь найти решение, которое не включает установку приложений / инструментов вне тех, которые обычно находятся в дистрибутивах Linux.


ВАЖНЫЙ:

Я хотел бы что-то вроде гипотетического примера ниже. В этом случае мы используем две переменные Shell (Bash).

ПРИМЕР:

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"

ПРИМЕЧАНИЕ: мы используем awk только для иллюстрации!

2 ответа2

2

Я предполагаю, что это можно сделать лучше с помощью awk , но это лучшее, что я могу предложить.

grep -zo "Bluetooth\s*Soft blocked: no\s*Hard blocked: no" file_name | grep -c "Bluetooth"

-z заставляет grep рассматривать весь файл как одну строку.

-o записывает только вывод, соответствующий строке, а не всю строку.
(в нашем случае с -z это будет означать весь файл)

\s соответствует пустым символам и новым строкам.

Второй экземпляр grep будет искать только слово "Bluetooth" в выходных данных первого вызова grep .

-c заставляет grep записывать количество совпадающих регулярных выражений вместо совпадений.

0

Немного неясно, как вы хотите сопоставить (ваш дополнительный пример в комментарии выше не проливает свет), однако предположим, что вы сохраняете свой строковый блок с сетевой информацией внутри string файла и блок подстроки внутри substring файла ,

Используя следующий подход, вы получите то, что я понимаю, вы ожидали: 2 матча.

cat string | tr -s " " | tr '\n' '@' | grep -o "$(cat substring | tr -s " " | tr '\n' '@')" | wc -l

По сути, обе строки сжаты в одну строку, игнорируя пробелы или табуляции и преобразуя символы новой строки в @ . Используя синтаксис grep -o , мы печатаем все вхождения (-o) найденного шаблона.

Однако неясно, ожидаете ли вы в вашем примере совпадения 0 раз (точное позиционное совпадение) или 2 раза (игнорируя предварительно добавленный текст). Это очень похоже на то, что Iskustvo разместил здесь ; может быть, мы неправильно поняли ваше намерение?

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .