Мне нужно посчитать все '=' между двумя шаблонами, то есть '{' и '}'. Пример:

{
100="1";
101="2";
102="3";
}; 
{
104="1,2,3";
};
{
105="1,2,3";
};

Ожидаемый результат:

3
1
1
-1
Shashwat Shekhar Shukla 2 Янв 2016 в 01:36

4 ответа

Лучший ответ

Очень загадочный ответ на Perl:

perl -nE 's/\{(.*?)\}/ say ($1 =~ tr{=}{=}) /ge'

Функция tr возвращает количество транслитерированных символов.


С новыми требованиями мы можем внести пару небольших изменений:

perl -0777 -nE 's/\{(.*?)\}/ say ($1 =~ tr{=}{=}) /ges'
  • -0777 считывает весь файл / поток в одну строку
  • флаг s функции s/// позволяет . обрабатывать символы новой строки как простой символ.
1
glenn jackman 2 Янв 2016 в 13:37

AWK тоже здесь

grep -o '{[^}]\+}'|awk -v FS='=' '{print NF-1}'

Пример

echo '{100="1";101="2";102="3";}; 
{104="1,2,3";};
{105="1,2,3";};'|grep -o '{[^}]\+}'|awk -v FS='=' '{print NF-1}'

Выход

3
1
1
0
repzero 2 Янв 2016 в 00:11

Perl на помощь:

perl -lne '$c = 0; $c += ("$1" =~ tr/=//) while /\{(.*?)\}/g; print $c' < input
  • -n читает входные данные построчно
  • -l добавляет новую строку к каждому print
  • /\{(.*?)\}/g - регулярное выражение. ? делает звездочку экономной, т. Е. Соответствует самой короткой строке.
  • Скобки (...) создают группу захвата, называемую $1.
  • tr обычно используется для транслитерации (т. Е. Замены одного символа другим), но здесь он просто подсчитывает количество знаков равенства.
  • += добавляет число к $c.
1
choroba 1 Янв 2016 в 23:19

Сначала некоторый тестовый ввод (строка с = вне фигурных скобок и внутри содержимого, одна без скобок и одна только с двумя скобками)

echo '== {100="1";101="2";102="3=3=3=3";} =; 
a=b
{c=d}
{}'

Обрабатывать строку без скобок (поместите фиктивный символ, чтобы не получить пустую строку)

sed -e 's/^[^{]*$/x/' 

Обрабатывать строку без знака равенства (поместите фиктивный символ, чтобы не получить пустую строку)

sed -e 's/{[^=]*}/x/' 

Убираем вещи за скобками

sed -e 's/.*{\(.*\)}/\1/'

Удалите содержимое в двойных кавычках (не считайте поля там)

sed -e 's/"[^"]*"//g' 

Используйте метод @repzero для подсчета знаков равенства

awk -F "=" '{print NF-1}'

Комбинировать вещи

echo -e '{100="1";101="2";102="3";};\na=b\n{c=d}\n{}' | 
   sed -e 's/^[^{]*$/x/' -e 's/{[^=]*}/x/' -e 's/.*{\(.*\)}/\1/' -e 's/"[^"]*"//g' | 
   awk -F "=" '{print NF-1}'

Уродливые временные поля x и замену {} можно решить внутри awk:

echo -e '= {100="1";101="2=2=2=2";102="3";};\na=b\n{c=d}\n{}' | 
   sed -e 's/^[^{]*$//' -e 's/.*{\(.*\)}/\1/' -e 's/"[^"]*"//g' | 
   awk -F "=" '{if (NF>0) c=NF-1; else c=0; print c}'

Или короче

echo -e '= {100="1";101="2=2=2=2";102="3";};\na=b\n{c=d}\n{}' |
   sed -e 's/^[^{]*$//' -e 's/.*{\(.*\)}/\1/' -e 's/"[^"]*"//g' |
   awk -F "=" '{print (NF>0) ? NF-1 : 0; }'
0
Walter A 2 Янв 2016 в 09:41