Подсчет количества вхождений символов в строке

У меня есть файл, который выглядит следующим образом: (Примечание: A*, B*, C* являются заполнителями). Файл ограничен ;

AAAA;BBBB;CCCCCCCC;DD;EEEEEEEE;FF;
AAA1;BBBBB;CCCC;DD;EEEEEEEE;FFFFF;
AAA3;BB;CCCC;DDDDDDDDD;EEEEEEE;FF;

Я пытаюсь написать небольшой скрипт, который подсчитывает количество вхождений разделителя ; и если оно меньше или больше 5, выведите указанную строку в текстовый файл.

delim=";"

while read line
do  
    n_of_occ=$(grep -o "$delim" <<< "$line" | wc -l)

    if [[ $n_of_occ < 5 ]] || [[ $n_of_occ > 5 ]]
    then
        echo $line >> outfile
    fi
done

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

5 ответов

Решение

К сожалению, каждая строка в ваших данных образца имеет шесть точек с запятой, что означает, что все они должны быть напечатаны. Тем не менее, вот решение Perl, состоящее из одной строки

$ perl -ne'print if tr/;// != 5' aaa.csv
AAAA;BBBB;CCCCCCCC;DD;EEEEEEEE;FF;
AAA1;BBBBB;CCCC;DD;EEEEEEEE;FFFFF;
AAA3;BB;CCCC;DDDDDDDDD;EEEEEEE;FF;

Это смешно легко с awk:

awk -F\; 'NF!=6' file > outfile

Легко в Perl:

perl -ne 'print if tr/;// != 5' input_file > output_file
  • -n читает входные данные построчно
  • tr оператор возвращает количество совпадений

Я бы взял эту однострочную:

awk '{x=$0}gsub(";","",x)!=5' file

С помощью sed вы можете сделать это:

sed '/^\([^;]*;\)\{5\}$/d' file > outfile

Удаляет строки ровно с 5 запятыми (;) и отправляет вывод в outfile.


Или, если вы хотите, чтобы ваш собственный код работал, внесите следующие изменения:

  1. замещать done с done <file
  2. замещать [[ с (( а также ]] с )) т.е. использовать ((...)) вместо [[...]]
Другие вопросы по тегам