Bash: Как посчитать количество вхождений символа в строке

1 minute read

Для того что бы в bash скрипте посчитать количество вхождений символа (баквы, цифры, знака) в строке можно воспользоваться функционалом grep и wc:

grep -o `/` <<< $string |wc -l

В этом примере

  • $string - произвольная строка
  • / - разделитель

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

Если в строке Вам нужно отсечь 5-ю колонку или каждое пятое поле после разделителя - очень просто это делается с помощью утилит cut или awk.

На пример, у нас есть вот такой набор строк, оюъеденных в список:

list=`'asd|fgh|jkl  
qwe|rty|uio  
zxc|vbn|nm<`'

Выводим второй элемент каждой строки:

for f in $list; do echo $f |awk -F`|` '{print $2}';done

или

for f in $list; do echo $f |cut -d `|` -f 2;done

В результате получаем:

fgh  
rty  
vbn

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

Для примера буду использовать вот такой список:

list=`'asd|fgh|jkl|123  
qwe|rty|uio|p[]|<?.|456  
zxc|vbn|789`'

Нужно получить цифры.

В таком случае есть тва трюка:

  1. С помощью sed добавить еще один разделитель в конец каждой строки и отрезать предпоследний элемент
  2. С помощью bc добавить 1 к значению количества вхождений и отобразить этот эллемент.

Первый вариант:

for f in $list;
do
  echo $f |cut -d "|" -f $(echo $f |sed 's/$/\|/g' |grep -o "|" |wc -l)
done

В примере:
echo $f |sed 's/$/\|/g' |grep -o "|" |wc -l - делает сразу все: добавляет | в конец строки и считает количество вхождений.

Второй вариант:

for f in $list;
do
  echo $f |cut -d "|" -f $(bc <<< $(grep -o "|" <<< $f |wc -l)+1);
done

В примере:

  • grep -o "|" <<< $f |wc -l - считает количество вхождений разделителя “ ” в каждую из строк
  • bc <<< $(grep ...)+1 - добавляет единицу

Categories:

Updated: