Я хочу посчитать буквы A, T, C, G и N в файле или каждую букву, если необходимо, есть ли быстрая команда Unix, чтобы сделать это?
command-line
unix
shell
characters
Кирстин
источник
источник
[System.IO.File]::ReadAllText("C:\yourfile.txt").ToCharArray() | Group-Object $_ | Sort Count -Descending
Get-Content "C:\eula.3082.txt" | % { $_.ToCharArray() } | Group-Object | Sort Count -Descending
Ответы:
Если вам нужна реальная скорость:
Это невероятно быстрый псевдо-один лайнер.
Простой тест показывает, что на моем процессоре Core i7 870 @ 2,93 ГГц он составляет чуть более 600 МБ / с:
В отличие от решений, связанных с сортировкой, этот работает в постоянной (4 КБ) памяти, что очень полезно, если ваш файл намного больше, чем ОЗУ.
И, конечно же, немного смазав локоть, мы можем сбрить 0,7 секунды:
Сети чуть более 1,1 ГБ / с, заканчивающиеся в:
Для сравнения я проверил некоторые другие решения на этой странице, которые, казалось, имели какое-то обещание скорости.
Решение
sed
/awk
сделал доблестное усилие, но умер через 30 секунд. С таким простым регулярным выражением, я ожидаю, что это будет ошибка в sed (GNU sed версия 4.2.1):Метод perl тоже казался многообещающим, но я сдался после запуска в течение 7 минут
источник
grep -o foo.text -e A -e T -e C -e G -e N -e -|sort|uniq -c
Сделаем трюк как один лайнер. Небольшое объяснение необходимо, хотя.
grep -o foo.text -e A -e T -e C -e G -e N -e -
greps файл foo.text для букв a и g и символа-
для каждого символа, который вы хотите найти. Он также печатает один символ в строке.sort
сортирует это по порядку. Это создает основу для следующего инструментаuniq -c
считает повторяющиеся повторения любой строки. В этом случае, поскольку у нас есть отсортированный список символов, мы получаем точное количество символов, которые мы выделили на первом шаге.Если бы foo.txt содержал строку,
GATTACA-
это то, что я получил бы из этого набора команд.источник
-o
.Попробуйте, вдохновленный ответом @ Journeyman.
Ключ знает о опции -o для grep . Это разделяет совпадение, так что каждая выходная строка соответствует одному экземпляру шаблона, а не всей строке для любой совпадающей строки. Учитывая эти знания, нам нужен только шаблон и способ подсчета строк. Используя регулярное выражение, мы можем создать дизъюнктивный шаблон, который будет соответствовать любому из указанных вами символов:
Это означает «соответствует A или T или C или G или N или -». Руководство описывает различные синтаксисы регулярных выражений, которые вы можете использовать .
Теперь у нас есть вывод, который выглядит примерно так:
Нашим последним шагом является объединение и подсчет всех похожих строк, что можно просто выполнить с помощью a
sort | uniq -c
, как в ответе @ Journeyman. Сортировка дает нам вывод, как это:Который, когда по каналу
uniq -c
, в конце концов напоминает то, что мы хотим:Приложение: Если вы хотите подсчитать количество символов A, C, G, N, T и - в файле, вы можете
wc -l
вместо этого передать по конвейеру вывод grepsort | uniq -c
. Есть много разных вещей, которые вы можете посчитать с небольшими изменениями в этом подходе.источник
Один лайнер, подсчитывающий все буквы с использованием Python:
... создавая дружественный YAML вывод, как это:
Интересно посмотреть, как в большинстве случаев Python может легко превзойти даже bash с точки зрения ясности кода.
источник
Похож на
awk
метод Гуру :источник
После использования UNIX в течение нескольких лет вы очень хорошо разбираетесь в нескольких небольших операциях для выполнения различных задач фильтрации и подсчета. У каждого свой стиль - некоторым нравится,
awk
а другимsed
нравитсяcut
иtr
. Вот как я бы это сделал:Чтобы обработать определенное имя файла:
или в качестве фильтра:
Это работает так:
od -a
разделяет файл на символы ASCII.cut -b 9-
исключает префиксod
ставит.tr " " \\n
преобразует пробелы между символами в новые строки, так что в каждой строке по одному символу.egrep -v "^$"
избавляется от всех лишних пустых строк, которые это создает.sort
собирает экземпляры каждого персонажа вместе.uniq -c
считает количество повторов каждой строки.Я кормил его "Привет, мир!" с последующим переводом строки и получил это:
источник
sed
Часть базируясь на ответ @ Гуру , вот еще один подход с использованиемuniq
, аналогично решению Дэвида Шварца.источник
[[:alpha:]]
а не.
в,sed
чтобы соответствовать только символы, а не переводы строк.[[:alpha:]]
потерпит неудачу, если вы также попытаетесь сопоставить такие вещи, как-
, что было упомянуто в вопросеsed -e 's/[^ATCGN-]//g' -e 's/\([ATCGN-]\)/\1\n/g' foo | sort | uniq -c
. Тем не менее, я не знаю, как избавиться от новой строки там: \Вы можете комбинировать
grep
иwc
делать это:grep
выполняет поиск указанного файла (-ов) по указанному тексту, и-o
опция указывает ему печатать только фактические соответствия (т. е. символы, которые вы искали), а не значение по умолчанию, которое должно печатать каждую строку, в которой был найден текст поиска найти на.wc
печатает количество байтов, слов и строк для каждого файла или, в этом случае, выводgrep
команды.-w
Опция говорит его подсчет количества слов, причем каждое слово является вхождение поискового характера. Конечно,-l
опция (которая считает количество строк) также будет работать, так какgrep
каждое вхождение вашего символа поиска выводится на отдельной строке.Чтобы сделать это для нескольких символов одновременно, поместите символы в массив и зациклите его:
Пример: для файла, содержащего строку
TGC-GTCCNATGCGNNTCACANN-
, вывод будет:Для получения дополнительной информации см
man grep
иman wc
.Недостатком этого подхода, как замечает пользователь Journeyman Geek ниже в комментарии, является то, что
grep
его нужно запускать один раз для каждого персонажа. В зависимости от размера ваших файлов это может привести к заметному снижению производительности. С другой стороны, когда это делается таким образом, становится немного проще быстро увидеть, какие символы ищут, и добавить / удалить их, так как они находятся на отдельной строке от остальной части кода.источник
uniq -c
также кажется лучшим способом получить красиво отформатированный вывод. Я не гуру * nix, вышеизложенное - это то, что мне удалось собрать из моих ограниченных знаний и нескольких страниц руководства :)Используя строки последовательности из 22hgp10a.txt, разница во времени между grep и awk в моей системе делает использование awk способом ...
[Редактировать]: После просмотра скомпилированного решения Дейва, забудьте также awk, так как его выполнение заняло ~ 0,1 секунды в этом файле для полного учета регистра с учетом регистра.
Версия ghostdog без учета регистра завершается за ~ 14 секунд.
Сед объяснен в принятом ответе на этот вопрос .
Бенчмаркинг как в принятом ответе на этот вопрос .
Принятый ответ от ghostdog74 был на этот вопрос .
источник
s/cache[letters[x]]/cache[letters[x]]+cache[toupper(letters[x])]
использовать его, чтобы сделать его нечувствительным к регистру, не влияя на его скорость.Я думаю, что любая достойная реализация избегает сортировки. Но так как плохая идея читать все 4 раза, я думаю, что можно каким-то образом сгенерировать поток, который проходит через 4 фильтра, по одному на каждый символ, который отфильтровывается и где длины потока также каким-то образом рассчитываются.
Тогда накопленные суммы находятся в tmp [0-6] .txt .., поэтому работа еще продолжается
В этом подходе всего 13 каналов, что позволяет преобразовать менее 1 МБ памяти.
Конечно, мое любимое решение:
источник
tr
.Я не знал
uniq
ни оgrep -o
, ни о , но, поскольку мои комментарии к @JourneymanGeek и @ crazy2be имели такую поддержку, возможно, мне стоит превратить его в своего собственного ответчика:Если вы знаете, что в вашем файле есть только «хорошие» символы (те, которые вы хотите посчитать), вы можете перейти к
Если только некоторые символы должны учитываться, а другие нет (т.е. разделители)
Первый использует подстановочный знак регулярного выражения
.
, который соответствует любому отдельному символу. Второй использует «набор принятых символов», без определенного порядка, за исключением того, что-
должен стоять последним (A-C
интерпретируется как «любой символ междуA
иC
). В этом случае требуются кавычки, чтобы ваша оболочка не пыталась расширить ее, чтобы проверить односимвольные файлы, если они есть (и выдает ошибку «нет совпадения», если ее нет).Обратите внимание, что «sort» также имеет
-u
флаг «nique», так что он сообщает об этом только один раз, но не имеет сопутствующего флага для подсчета дубликатов, поэтомуuniq
действительно является обязательным.источник
-
не должен идти последним, если вы избежите его с обратной косой чертой:'[A\-CTGN]'
должно работать просто отлично.Глупый
tr
удалить (-d
) все символы, кроме (-c
) ATCGN-iconv
преобразовать в ucs2 (UTF16 ограничен 2 байтами), чтобы добавить 0 байт после каждого байта,tr
для перевода этих символов NUL в NL. Теперь каждый персонаж находится на своей линииsort | uniq -c
считать каждую уникальную строкуЭто альтернатива нестандартной (GNU)
-o
опции grep.источник
Формат вывода не самый лучший ...
Теория Операции:
Скорость, кажется, составляет 60 Мбит / с +
источник
Образец файла:
Команда:
источник
Объединяя несколько других
Добавьте,
| sort -nr
чтобы увидеть результаты в порядке частоты.источник
Краткий ответ:
Если обстоятельства позволяют, сравните размеры файлов с низкими наборами символов с одним без символов, чтобы получить смещение и просто считать байты.
Ах, но запутанные детали:
Это все персонажи Ascii. Один байт на. В файлах, конечно, есть дополнительные метаданные, предваряемые для различных вещей, используемых ОС и приложением, которое ее создало. В большинстве случаев я ожидал бы, что они будут занимать одинаковое количество места независимо от метаданных, но я постараюсь сохранить идентичные обстоятельства, когда вы сначала проверяете подход, а затем проверяете, что у вас есть постоянное смещение, прежде чем беспокоиться об этом. Другая проблема заключается в том, что разрывы строк обычно включают два символа пробела ascii, и любые табуляции или пробелы будут по одному на каждой. Если вы можете быть уверены, что они будут присутствовать, и нет никакого способа узнать, сколько их заранее, я бы прекратил читать сейчас.
Это может показаться большим количеством ограничений, но если вы можете легко их установить, это выглядит как самый простой / наиболее эффективный подход, если у вас есть тонна из них, чтобы рассмотреть (что, вероятно, если это ДНК). Проверка тонны файлов на длину и вычитание константы будет быстрее, чем выполнение grep (или аналогичного) для каждого.
Если:
И две вещи, которые могут не иметь значения, но я бы попробовал сначала
Попробуйте найти смещение, выполнив следующие действия:
Сравните пустой файл с файлом, содержащим несколько легко подсчитываемых человеком символов, с файлом, содержащим несколько символов. Если вычитание пустого файла из двух других файлов даст вам количество байтов, соответствующее количеству символов, все готово. Проверьте длину файла и вычтите это пустое количество. Если вы хотите попытаться выяснить многострочные файлы, большинство редакторов прикрепляют два специальных однобайтовых символа для разрывов строк, поскольку один из них, как правило, игнорируется Microsoft, но вам придется по крайней мере использовать grep для символов пробела в этом случае Вы могли бы также сделать все это с помощью grep.
источник
Haskell путь:
это работает так:
составление и использование:
не подходит для больших файлов, может быть.
источник
Quick Perl Hack:
-n
: Перебирать входные строки, но ничего для них не печатать-l
: Автоматическое удаление или добавление разрывов строкwhile
: перебрать все вхождения запрошенных символов в текущей строкеEND
: В конце распечатать результаты%a
: Хэш, где хранятся значенияСимволы, которые вообще не встречаются, не будут включены в результат.
источник