У меня есть текстовый файл, в каждой строке слова разделены запятыми, вот так:
7022122465,0,\N,,0,2015-09-29 10:48:33
7022597642,0,\N,,0,2015-09-29 10:48:33
7022848906,0,\N,,0,2015-09-29 10:48:33
7022848906,5,\N,,0,2015-09-29 10:48:33
7022848906,55,\N,,0,2015-09-29 10:48:33
.....................................etc
Я хочу подсчитать ненулевые числа во втором столбце, используя только команду sed
or grep
в Linux/UNIX.
Примечание
Без использования других команд:
cut -d',' -f2 < KAR_UBONA_UBONACT15_20150929_20150930_FEEDBACK.txt | grep -vcw 0
Но я не хочу cut
только этого, мне нужно использовать grep
.
решение1
Вы можете использовать -c
опцию grep. И вы можете удалить все символы до первой запятой и все, что от второй запятой, с помощью sed
:
sed 's/^[^,]*,//;s/,.*//' < the_file | grep -c -E '[^0]'
EDIT: Эта sed
команда делает то же самое, что и ваша cut
команда, поэтому вы также сможете использовать свою оригинальную grep
команду.
EDIT2: Если вы хотите использовать только одну команду, вы можете использовать @cuonglm grp answer. Если вы хотите использовать толькоодин призывпридется sed
много работать с метками, чтобы в конце подсчитать количество строк.
sed -E -n '
s/^[^,]*,[^0,]+,.*/+1/ # replace the lines we are interested in with "+1"
T delete_line # if we did not do a substitution right now we jump to "delete_line"
H # we did not jump (so we did the substitution and append the "+1" to the hold space
: delete_line # the label, here we do nothing (silently drop the current line)
$ { # on the last line we ...
s/.*/0/ # replace the whole line with "0"
G # append the hold space (all the "+1" from before")
s/\n//g # remove all newlines
p # print the line
}' < the_file
Теперь это можно передать по конвейеру bc
или заменить p
команду какой-нибудь сложной sed
магией, чтобы суммировать эти числа в sed
. Я думаю, я слышал, что sed
это Тьюринг-полный код, так что это должно быть возможно.
Если вы хотите использовать толькоодна программа( sed
) но не стоит вызывать его несколько раз, так гораздо проще:
sed '/^[^,]*,0,.*/d' < the_file | sed -n '$='
решение2
С grep
:
grep -c '^[^,]*,[^0]' <file
Это работает только если 2-й столбец сформирован как целое число, но не -0
, +0
. Для более общего случая см.Ответ @Stéphane Chazelas.
решение3
grep -c '^[^,]*,[-+0-9.]*[1-9]'
Это должно охватывать числа, выраженные как 12
, -1
, 0e+12
, 01
, 0.0001
. Но не для 0xFF
или Inf
или NaN
, например, так что это все равно будет отличаться от более канонического:
POSIXLY_CORRECT=1 awk -v n=0 -F , '$2 != 0 {n++}; END{print n}'
Если ваши входные данные содержат числа, выраженные в таком формате.
В качестве sed
единственного решения вы можете сделать следующее:
sed '/^[^,]*,[-+0-9]*[1-9]/!d' | sed -n '$='
Но для решения всего с одним sed
вызовом нам пришлось бы выполнять арифметические действия вручную.
sed -n '
1{x;s/$/0,:0123456789,0/;x;}
/^[^,]*,[-+0-9]*[1-9]/ {
x;:1
s/^,/1/;s/\(.\),\(.*:.*\1\(,*.\)\)/\3\2/;t1
s/:/,:/
x
}
${x;s/,.*//p;}'