Как использовать grep для поиска строк, в которых любое слово встречается 3 раза?

Я бы предложил создать архив в два этапа:

  1. Создайте архив, исключив все, что хотите исключить:

    zip -r application.zip. -x 'vendor/*' 'node_modules/*' '.git/*'.env 'public/assets/images/*'
    
  2. Добавьте в тот же архив одну папку, которую вы хотите включить из исключенного каталога:

    zip -r application.zip public/assets/images/icons/
    

(поведение по умолчанию zipзаключается в добавлении файлов в существующий архив, если он уже существует)

5
02.12.2020, 15:45
5 ответов

Используя стандартное определение слова,

  • GNU Grep, 3 или более вхождения любого слова .

    grep -E '(\W|^)(\w+)\W(.*\<\2\>){2}' file
    

  • GNU Grep, только 3 вхождения любого слова .

    grep -E '(\W|^)(\w+)\W(.*\<\2\>){2}' file | grep -Ev '(\W|^)(\w+)\W(.*\<\2\>){3}'
    

  • POSIX Awk, только 3 появления любого слова .

    awk -F '[^_[:alnum:]]+' '{           # Field separator is non-word sequences
        split("", cnt)                   # Delete array cnt
        for (i=1; i<=NF; i++) cnt[$i]++  # Count number of occurrences of each word
        for (i in cnt) {
            if (cnt[i]==3) {             # If a word appears exactly 3 times
                print                    # Print the line
                break
            }
        }
    }' file
    

    Для 3 или более вхождений просто измените ==на >=.

    Эквивалентный лайнер с одним гольфом -:

    awk -F '[^_[:alnum:]]+' '{split("",c);for(i=1;i<=NF;i++)c[$i]++;for(i in c)if(c[i]==3){print;next;}}' file
    

  • GNU Awk, только 3 вхождения слова ab.

    gawk 'gsub(/\<ab\>/,"&")==3' file
    

    Для 3 или более вхождений просто измените ==на >=.


Материалы для чтения

13
18.03.2021, 22:46

Вот так?

egrep '(\<.+\>).+\<\1\>.+\<\1\>'
  • egrep(илиgrep -E)включает расширенные регулярные выражения , необходимые для обратных ссылок
  • \<.+\>будет соответствовать любому слову длиной не менее 1 символа
    • \<соотв. \>соответствуют границам слов (в вашей попытке вы вообще не учли границы слов)
    • .+соответствует последовательности из одного или нескольких символов (в вашей попытке вы использовали .*, которая соответствует последовательности из нуля или более символов!)
  • использовать обратные -ссылки, чтобы проверить, встречается ли совпадающая последовательность во второй раз(\1)и в третий раз(\1снова ).
    • мы допускаем любую последовательность из одного или нескольких символов(.+)между совпадениями, поэтому «foo bar foo dorbs foo godly» будет соответствовать (слово «foo» встречается 3 раза ).
    • если вы хотите сопоставить только соседние слова (например. "foo foo foo" ), вместо этого используйте что-то вроде [[:space:]]+.
9
18.03.2021, 22:46

Я предполагаю, что ваш вопрос означает, что если какое-либо из слов в строке встречается хотя бы 3 раза, то выведите строку, иначе отбросьте ее. Я бы использовал awkдля более читаемого и настраиваемого решения :

.
awk -F '\\W+' '{
    delete c; for (i=1;i<=NF;i++) if (length($i) && ++c[$i]==3) {print; next}
}' file

Это цикл для всех полей, подсчитывающий их появление в строке. Если какое-либо слово достигает 3 раз, оно напечатает строку, удалит массив и перейдет к следующей строке. Также существует проверка длины поля, чтобы избежать печати любых подсчитанных пустых полей.

Здесь мы можем легко настроить значение «слова», добавив разные и/или множество разделителей полей, используя-F(стандартные BRE и ERE, поддерживаемые ). В приведенном выше разделе разделителями слов являются все символы, кроме _и[:alnum:]:awk -F '\\W+'или awk -F '[^_[:alnum:]]+', аналогичные границам слов с grep.

Для человеческого языка нам могут понадобиться другие границы слов, например все, кроме букв, например:awk -F '[^[:alpha:]]+'или кроме букв и цифр:awk -F '[^[:alnum:]]+'или включать не только подчеркивание, но и тире в слова:awk -F '[^-_[:alnum:]]+'.

Без установки -Fиспользуются только пробельные символы.

3
18.03.2021, 22:46

  • GNU sedв режиме расширенного регулярного выражения -Eдля обнаружения строк, в которых любое слово повторяется ровно 3 раза в строке.

$ r1='.*\<\1\>'
$ r2=$r1$r1 r3=$r2$r1
$ sed -Ee "
    /\<(\w+)\>$r2/! d
    /\<(\w+)\>$r3/d
" file

  • Perl использует хэши для хранения слова в качестве ключа и его количества в текущей строке в качестве значения.
$ perl -lne 'my %h;
    $h{$_}++ for /\w+/g;
    print if grep { $_ == 3 } values %h;
' file

0
18.03.2021, 22:46

grep -P '(\b\w+\b)(.*\b\1\b){2}'

См. объяснение и тестовые примеры вhttps://regex101.com/r/Kr2VUc/2. Вы также можете сделать этот случай -нечувствительным:

grep -P '(?i)(\b\w+\b)(.*\b\1\b){2}'

1
18.03.2021, 22:46

Теги

Похожие вопросы