Как я могу использовать grep для получения количества каналов ('|')?

StackOverflow https://stackoverflow.com/questions/612658

  •  03-07-2019
  •  | 
  •  

Вопрос

Я пытался:

 grep -c "\|" *.* 

Но это не сработало, так как дает неверное количество последовательных каналов.

Как я могу этого добиться?

Это было полезно?

Решение

Другой вариант, использующий Perl:

perl -e 'while(<>){$c+=tr/|/|/};print "$c\n"' *

В формате не одной строки это:

while(<>){
    $c += tr/|/|/
}
print "$c\n"

Строка while(<>){ - это магия Perl для чтения строк из файлов команды или из STDIN. Вы привыкаете к этому через некоторое время. Сама строка переходит в переменную с именем $_, которая является параметром по умолчанию для многих команд Perl. Например, tr, который работает почти так же, как tr(1), по умолчанию работает на $c. Я помещаю свои результаты в глобальную переменную my $c = 0;. (В полной программе лучше объявить ее лексической переменной с += вне цикла.) Оператор *.* добавляет результат команды <=> (количество символов канала в данном случае) к текущему значение <=>.

Просто использовать <=> - это явно более простой вариант. ; -)

Использование <=> - это DOSism, который вы вряд ли захотите использовать на UNIX-подобной платформе.

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

$ echo '||||
|||||' | perl -e 'while(<>){$c+=tr/|/|/};print "$c\n"'
9

Другие советы

Вы можете использовать tr(1), чтобы удалить все непузырьковые символы, а затем использовать wc(1), чтобы получить общее количество:

cat *.* | tr -d -c '|' | wc -c

Это нелогично, но в большинстве регулярных выражений Unix экранирование | делает его оператором or. Таким образом, ваша строка фактически соответствует & Quot; ничто или ничто & Quot; (Вы можете проверить это, добавив несколько вариантов с обеих сторон). Просто используйте

grep -c "|" *.*

Во-вторых, grep считает строки, а не символы. Вы можете использовать другой инструмент; или, если вы настаиваете на grep, вы можете поставить каждый " | " на своей собственной линии. Например, с помощью sed:

sed 's/|/|\n/g' *.*

Примечание: если вы используете sed, я советую много тестирования, чтобы убедиться, что он делает то, что вы думаете. Мне нужно было именно тогда.

Наконец, объедините ингредиенты:

cat *.*  |  sed 's/|/|\n/g'  |  grep -c "|"

К сожалению, это может не сработать, так как вы, вероятно, не используете unix (из-за *.*). Но, надеюсь, это объясняет проблему, которую я всегда нахожу странно обнадеживающей.

Если вы хотите найти несколько каналов, то

fgrep -o "|" | wc -l

Если вы хотите найти количество строк хотя бы с одним каналом,

fgrep -c "|"

попробуй

grep -c "\|" *.*

и прочтите несколько руководств по bash

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top