Я бы предложил создать архив в два этапа:
Создайте архив, исключив все, что хотите исключить:
zip -r application.zip. -x 'vendor/*' 'node_modules/*' '.git/*'.env 'public/assets/images/*'
Добавьте в тот же архив одну папку, которую вы хотите включить из исключенного каталога:
zip -r application.zip public/assets/images/icons/
(поведение по умолчанию zip
заключается в добавлении файлов в существующий архив, если он уже существует)
Используя стандартное определение слова,
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 или более вхождений просто измените ==
на >=
.
Материалы для чтения
\2
является обратной -ссылкой . \w
\W
\<
\>
специальные выражения в GNU Grep . [:alnum:]
POSIX . Вот так?
egrep '(\<.+\>).+\<\1\>.+\<\1\>'
egrep
(илиgrep -E
)включает расширенные регулярные выражения , необходимые для обратных ссылок \<.+\>
будет соответствовать любому слову длиной не менее 1 символа \<
соотв. \>
соответствуют границам слов (в вашей попытке вы вообще не учли границы слов).+
соответствует последовательности из одного или нескольких символов (в вашей попытке вы использовали .*
, которая соответствует последовательности из нуля или более символов!)\1
)и в третий раз(\1
снова ). .+
)между совпадениями, поэтому «foo bar foo dorbs foo godly» будет соответствовать (слово «foo» встречается 3 раза ).[[:space:]]+
. Я предполагаю, что ваш вопрос означает, что если какое-либо из слов в строке встречается хотя бы 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
используются только пробельные символы.
GNU sed
в режиме расширенного регулярного выражения -E
для обнаружения строк, в которых любое слово повторяется ровно 3 раза в строке.
$ r1='.*\<\1\>'
$ r2=$r1$r1 r3=$r2$r1
$ sed -Ee "
/\<(\w+)\>$r2/! d
/\<(\w+)\>$r3/d
" file
$ perl -lne 'my %h;
$h{$_}++ for /\w+/g;
print if grep { $_ == 3 } values %h;
' file
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}'