Як порахувати кількість символів у рядку, крім конкретного символу?


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для заміни речей, які вас не цікавлять, і awkпорахуйте кількість, що залишиласяsed '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 / пробілу та порожнього рядка ...
Пн

1
@ Sundeep Так, це правильно. дивіться також моє оновлення, де рядки містять лише вкладки або пробіли, щоб вказати 0
αғsnιη

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може бути повільніше .
agc

ну я точно не переживаю часу на дрібні речі ... дивіться unix.stackexchange.com/questions/169716/…
Sundeep

1
@Sundeep, я робити занепокоєння. Деякий час тому я використовував дискети Linux на базі дискети , які могли бігти з дискети, в декількох мегах оперативної пам’яті. Зазвичай використання awkсценарію оболонки може змусити таку систему сканувати на четвереньках. Як правило: однакове перетягування затримки застосовується до систем з обмеженою прошивкою або будь-якої системи з великим навантаженням.
agc

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.