Подтвердить что ты не робот

Считать длину строк в файле с помощью инструментов командной строки

Проблема

Если у меня есть длинный файл с большим количеством строк различной длины, как я могу подсчитать вхождения каждой длины строки?

Пример:

file.txt

this
is
a
sample
file
with
several
lines
of
varying
length

Запуск count_line_lengths file.txt даст:

Length Occurences
1      1
2      2
4      3
5      1
6      2
7      2

Идеи?

4b9b3361

Ответ 1

count.awk:

{
  print length($0);
}

...

$ awk -f count.awk input.txt | sort | uniq -c
      1 1
      2 2
      3 4
      1 5
      2 6
      2 7

Ответ 2

Чистый awk

awk '{++a[length()]} END{for (i in a) print i, a[i]}' file.txt

4 3
5 1
6 2
7 2
1 1
2 2

Ответ 3

Использование bash массивов:

#!/bin/bash

while read line; do
    ((histogram[${#line}]++))
done < file.txt

echo "Length Occurrence"
for length in "${!histogram[@]}"; do
    printf "%-6s %s\n" "${length}" "${histogram[$length]}"
done

Пример выполнения:

$ ./t.sh
Length Occurrence
1      1
2      2
4      3
5      1
6      2
7      2

Ответ 4

$ perl -lne '$c{length($_)}++ }{ print qq($_ $c{$_}) for (keys %c);' file.txt

Выход

6 2
1 1
4 3
7 2
2 2
5 1

Ответ 5

Вы можете выполнить это, используя только основные утилиты unix:

$ printf "%s %s\n" $(for line in $(cat file.txt); do printf $line | wc -c; done | sort -n | uniq -c | sed -E "s/([0-9]+)[^0-9]+([0-9]+)/\2 \1/")
1 1
2 2
4 3
5 1
6 2
7 2

Как это работает?

  • Вот исходный файл:
    $ cat file.txt
    this
    is
    a
    sample
    file
    with
    several
    lines
    of
    varying
    length
    
  • Заменить каждую строку исходного файла на длину:
    $ for line in $(cat file.txt); do printf $line | wc -c; done
    4
    2
    1
    6
    4
    4
    7
    5
    2
    7
    6
    
  • Сортировка и подсчет количества вхождений длины:
    $ for line in $(cat file.txt); do printf $line | wc -c; done | sort -n | uniq -c
          1 1
          2 2
          3 4
          1 5
          2 6
          2 7
    
  • Обмен и форматирование номеров:
    $ printf "%s %s\n" $(for line in $(cat file.txt); do printf $line | wc -c; done | sort -n | uniq -c | sed -E "s/([0-9]+)[^0-9]+([0-9]+)/\2 \1/") 
    1 1
    2 2
    4 3
    5 1
    6 2
    7 2
    

Ответ 6

Если вы разрешаете менять столбцы и не нуждаетесь в заголовках, то это так просто, как

while read line; do echo -n $line | wc -m; done < file | sort | uniq -c

(без каких-либо продвинутых трюков с sed или awk) будет работать. Вывод:

1 1
2 2
3 4
1 5
2 6
2 7

Следует помнить одну важную вещь: wc -c считает байты, а не символы, и не даст правильную длину для строк, содержащих многобайтовые символы. Поэтому использование wc -m.

Рекомендации:

man uniq (1)

мужской сорт (1)

мужской туалет (1)