У меня есть файл, которого я должен считать все частичные соответствия для входной строки в файле.
Я покажу Вам легкий пример того, в чем я нуждаюсь:
В файле с этим содержанием:
Good-Black-Cat
Bad-Red-Cat
Bad-Gray-Dog
Good-Golden-Dog
Bad-White-Dog
Good-Tabby-Cat
Bad-Siamese-Cat
Я должен рассчитать, сколько раз делает частичную строку, "Хорошую - *-CAT" (Где * могло быть что-либо, это не имеет значения), появляется. Ожидаемое выходное количество равняется 2.
Любая справка будет цениться.
sed 's/\(Good-[^ ]*-Cat\)/XXXX\n/g' input.txt | grep -c XXXX
, В то время как XXXX
может быть любой шаблон, который не появляется иначе в Вашем файле. Этот подход заменяет все соответствия XXXX
шаблон и новая строка, так для создания этого легко исчисляемым основным выражением GREP.
Между прочим, если Вы берете, "Где * могло быть что-либо" буквально, по крайней мере, к моему пониманию, вывод любой такой программы всегда будет 0 или 1, таким образом, я предположу, что это не должно содержать пространство, по крайней мере.
Данный
$ cat file
Good-Black-Cat
Bad-Red-Cat
Bad-Gray-Dog
Good-Golden-Dog
Bad-White-Dog
Good-Tabby-Cat
Bad-Siamese-Cat
затем
$ grep -c 'Good-.*-Cat' file
2
Обратите внимание, что это - количество согласующих отрезков длинной линии - так, например, оно не будет работать на несколько случаев на строку, или на случаи тот промежуток строки.
С другой стороны, с awk
awk '/Good-.*-Cat/ {n++} END {print n}' file
Если бы необходимо соответствовать нескольким возможным случаям на строку, то я предложил бы perl
:
perl -lne '$c += () = /Good-.*?-Cat/g }{ print $c' file
где /Good-.*?-Cat/g
соответствия многократно (g
) и нежадно* (.*?
) и () =
присвоение вынуждает соответствия быть оцененными в скалярном контексте, таким образом, мы можем добавить их к количеству.
С другой стороны, Вы могли использовать grep
в режиме регулярного выражения perl-comparible (PCRE) (чтобы включить нежадный модификатор), с -o
для вывода только частей соответствия - затем считают тех, которые имеют wc
:
grep -Po 'Good-.*?-Cat' file | wc -l
Если также необходимо соответствовать случаям, которые могут охватить границу строки, то можно сделать так в perl
путем сбрасывания разделителя записей (примечание: это означает, что это целый файл хлебают в память), и добавление s
модификатор regex, например.
perl -0777 -nE '$c += () = /Good-.*?-Cat/gs }{ say $c' file
$ awk '{for(i=1;i<=NF;i++ ) count+=match($i,/Good-.*-Cat/)};END{print count}' input.txt
4
$ cat input.txt
Good-Black-Cat
Bad-Red-Cat
Bad-Gray-Dog
Good-Golden-Dog Good-Whatever-Cat Good-Something-Cat
Bad-White-Dog
Good-Tabby-Cat
Bad-Siamese-Cat
Это использует отрицательное сопоставление с образцом //!
с d
для удаляют, оставляя только строки интереса.
$ sed '/Good-.*-Cat/!d' input.txt
Good-Black-Cat
Good-Golden-Dog Good-Whatever-Cat
Good-Tabby-Cat
$ sed '/Good-.*-Cat/!d' input.txt | wc -l
3
Вот является оболочка путем, который объединяется case...esac
и читающий файл цикл:
$ n=0; while IFS= read -r line || [ -n "$line" ]; do case "$line" in "Good-"*"-Cat") n=$((n+1));; esac; done < input.txt; echo "$n"
2
Или с indientation
n=0
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
"Good-"*"-Cat") n=$((n+1));;
esac
done < input.txt
echo "$n"
Объяснение:
n=0
инициализирует n
переменная счетчикаwhile IFS= read -r line || [ -n "$line" ]; do...done < input.txt
стандартный читающий файл цикл, используемый в сценариях оболочки, с || [ -n "$line" ]
защита для составления возможных файлов, которые не заканчиваются в новой строкеcase "$line" in "Good-"*"-Cat") n=$((n+1));; esac
сопоставление с образцом для желаемой строки с $((...))
арифметическое расширение для постепенного увеличения переменной счетчика.