Как посчитать количество символов в строке, кроме конкретного символа?


9

Это часть файла

N W N N N N N N N N N
N C N N N N N N N N N
N A N N N N N N N N N
N N N N N N N N N N N
N G N N N N N N N N N
N C N N N C N N N N N
N C C N N N N N N N N

В каждой строке я хочу подсчитать общее количество всех символов, которые не являются "N"

вывод моего желания

1
1
1
0
1
2
2

Используйте, sedчтобы заменить вещи, которые вам не awksed 's/N//g ; s/\s//g' file | awk '{ print length($0); }'
Рольф

Ответы:


13

GNU awk решение:

awk -v FPAT='[^N[:space:]]' '{ print NF }' file
  • FPAT='[^N[:space:]]'- шаблон, определяющий значение поля (любой символ, кроме Nсимвола и пробела)

Ожидаемый результат:

1
1
1
0
1
2
2


7

предполагая, что количество необходимо для каждой строки, кроме пробела и N

$ perl -lne 'print tr/N //c' ip.txt 
1
1
1
0
1
2
2
  • Возвращаемое значение tr- сколько символов было заменено.
  • c дополнить набор символов, данных
  • Обратите внимание на использование -lпараметра, удаляет символ новой строки из строки ввода, чтобы избежать ошибки, а также добавляет символ новой строки для оператора печати


Более общее решение

perl -lane 'print scalar grep {$_ ne "N"} @F' ip.txt 
  • -aвозможность автоматического разделения строки ввода на пробелы, сохраненные в @Fмассиве
  • grep {$_ ne "N"} @Fвозвращает массив всех элементов, в @Fкоторых не совпадает строкаN
    • эквивалент регулярного выражения будет grep {!/^N$/} @F
  • использование scalarдаст количество элементов массива

6

Альтернативное решение awk :

awk '{ print gsub(/[^N[:space:]]/,"") }' file
  • gsub(...)- gsub()Функция возвращает количество сделанных замен.

Выход:

1
1
1
0
1
2
2

6

Другой awkподход (вернет -1 для пустых строк).

awk -F'[^N ]' '$0=NF-1""' infile

Или в комплексе, он вернет -1 в пустых строках, 0 только в строках пробелов (табуляции / пробелов).

awk -F'[^N \t]+' '$0=NF-1""' infile

напечатает -1для пустых строк ... но тогда это было бы желательно , чтобы выделить строку, состоящую только из N / пространства против пустой строки ...
Sundeep

1
@ Сандип Да, это правильно. также смотрите мое обновление, где строки были только табуляции или пробелы, чтобы указать как 0
αғsнιη

5
  1. trи сценарий оболочки POSIX :

    tr -d 'N ' < file | while read x ; do echo ${#x} ; done
    
  2. bash, kshи zsh:

    while read x ; do x="${x//[ N]}" ; echo ${#x} ; done < file
    

1
можно использовать, awk '{print length()}'чтобы избежать более медленного зацикливания оболочки ... но тогда можно было бы делать все с помощью самого awk ...
Sundeep

@Sundeep, Это правда, ( если они оба начали в то же время), что awkзацикливание это быстрее , чем оболочка зацикливание. Но оболочка всегда находится в памяти и, awkвозможно, не будет - когда awkона еще не загружена или не выгружена, накладные расходы на ее загрузку ( потерянное время ) могут быть больше, чем преимущество при запуске, awkособенно на небольших петля. В таких случаях ( т.е. в этом случае), awkможет быть медленнее .
АРУ

ну, конечно, я не беспокоюсь о времени для мелочей
Sundeep

1
@Sundeep, я делать беспокойство. Некоторое время назад я использовал дистрибутивы Linux на дискетах , которые могли запускаться с дискет в несколько мегабайт оперативной памяти. Без необходимости использование awkв сценарии оболочки может заставить такую ​​систему ползать на четвереньках. Как правило: та же задержка перетаскивания применяется к системам с ограниченным программным обеспечением или любой системе с большой нагрузкой
АРУ

1

Краткая комбинация trи awk:

$ tr -d ' N' <file.in | awk '{ print length }'
1
1
1
0
1
2
2

Это удаляет все пробелы Ns из входного файла и awkпросто печатает длину каждой строки.


0

Другой простой способ - сделать это на python, который предустановлен в большинстве сред Unix. Перетащите следующий код в файл .py:

with open('geno') as f:
    for line in f:
        count = 0
        for word in line.split():
            if word != 'N':
                count += 1
        print(count)

А затем сделайте:

python file.py

С вашего терминала. Что выше делает:

  • для каждой строки в файле с именем "geno"
  • установите счетчик в 0 и увеличивайте его каждый раз, когда мы находим значение! = 'N'
  • когда будет достигнут конец текущей строки, выведите счетчик и перейдите к следующей строке
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.