#regex #bash #sed #grep #counting
#регулярное выражение #bash #sed #grep #подсчет
Вопрос:
Я хочу подсчитать количество совпадений в одной единственной строке (или во всех строках, поскольку всегда будет только одна строка).
Я хочу подсчитывать не только одно совпадение в строке, как в
echo "123 123 123" | grep -c -E "123" # Result: 1
Лучший пример:
echo "1 1 2 2 2 5" | grep -c -E '([^ ])( 1){1}' # Result: 1, expected: 2 or 3
Комментарии:
1. всегда ли данные разделяются пробелом?
2. Всегда будет только «одни данные», потому что, возможно, я хочу сопоставить
123 123
3 (или 2) раза в123 123 123 123
3. 1 за вопрос, -1 за странный пример регулярных выражений
Ответ №1:
Вы могли бы использовать grep -o
then pipe through wc -l
:
$ echo "123 123 123" | grep -o 123 | wc -l
3
Комментарии:
1. Моя версия grep не знает, что
-o
такое:(2. Вам нужно попросить Деда Мороза о новом grep в этом году. 🙂
3. @manojlds, у тебя есть
egrep
? То же самое будет работать с/egrep
4. @Mike Pennington — спасибо,
egrep
говорит то же самое. Я сейчас на Windows, поэтому думаю, что это ожидаемо.5. @Tylio — это неудивительно, посмотри на свое регулярное выражение. Запрашивается 0 или более экземпляров чего-либо, отличного от пробела, за которым следует пробел, за которым следует первое, что вы снова сопоставили. Примечание: 0 или более . В вашей строке действительно пять таких совпадений (при условии, что вы не перематываете после каждого совпадения). Это: 1)
"1 1"
(байты 1-3), 2)" "
(т. е. нулевые экземпляры чего-либо, что не является пробелом, за которым следует пробел, за которым снова те же нулевые экземпляры — байт 4), 3)"2 2"
(байты 5-7), 4)" "
(байт 8) и, наконец, 5)" "
(байт 10). Уф!
Ответ №2:
Может быть, ниже:
echo "123 123 123" | sed "s/123 /123n/g" | wc -l
(может быть, уродливо, но мой bash fu не настолько хорош)
Комментарии:
1. @Tyilo — что ты пробовал? Я получаю 3 для приведенных выше входных данных
2. Скопировал и вставил ваш код, но теперь я вспоминаю, что мой sed не поддерживает
n
Ответ №3:
Может быть, вам сначала следует преобразовать пробелы в новые строки:
$ echo "1 1 2 2 2 5" | tr ' ' $'n' | grep -c 2
3
Ответ №4:
Почему бы не использовать awk? Вы могли бы использовать awk '{print gsub(your_regex,"amp;")}'
для печати количества совпадений в каждой строке или awk '{c =gsub(your_regex,"amp;")}END{print c}'
для печати общего количества совпадений. Обратите внимание, что относительная скорость может варьироваться в зависимости от того, какая реализация awk используется и какой ввод вводится.
Комментарии:
1. Другим способом gawk является
gawk -v FPAT=your_regex '{print NF}'
илиgawk -v FPAT=your_regex '{c =NF}END{print c}'
соответственно.
Ответ №5:
Это может сработать для вас:
sed -n -e ':a' -e 's/123//p' -e 'ta' file | sed -n '$='
GNU sed можно было бы написать:
sed -n ':;s/123//p;t' file | sed -n '$='
Комментарии:
1. Первый скрипт не работает в GNU sed 4.2.2: «sed: не удается найти метку для перехода к
a'". It seems to work better, if you replace
:ta` by:a
. Похоже, скрипты требуют перевода строки в конце ввода. Кроме того, скрипт ничего не выводит, если совпадения не найдены. Тест:printf 123 | sed -n ':;s/123//p;t' | sed -n '$='
ничего не выводит.