[nix] Быстро обработать текстовый файл. Подскажите, по SED скрипту

Xomiak09

Написал код на баше который перед каждой строкой куска геномного кода ставит порядковый номер, например :
>SEQUENCE_1_length_35
G.CCCTGATCAGCCGGATGGGCAACCAGAAGGTCCG
>SEQUENCE_2_length_35
G.TCCACACCGGCATCCCCGAGCCGCGACATGCCGG
 
  #!/usr/bin/bash
len=$(wc -l s7.fa | awk '{print($1)}' )
len++
for i=1; i<$len; i+=1
do
echo '>SEQUENCE_'${i}'_length_35' >> s7_fasted.fa
head -n $i forSOAP_s7_final.fa | tail -n 1 >> s7_fasted.fa

done

Проблема, в том что количество строк для обработки огромное (~десятки миллионов)
, и за трое суток скрипт не успел обработать и 20 % инфы. Вопрос знатокам: может быть есть более быстрый способ ? Например sed...

yolki

я конечно понимаю, что сед полон по Тьюрингу, но может быть
программа на более высокоуровневом языке справится быстрее?

Maurog

for i=1; i<$len; i+=1
do
echo '>SEQUENCE_'${i}'_length_35' >> s7_fasted.fa
head -n $i forSOAP_s7_final.fa | tail -n 1 >> s7_fasted.fa
done
вижу квадрат
данную задачу надо решать линейным пробегом

Maurog

обычно на линуксах tcl есть (в баше я не спец :( )

#!/usr/bin/tclsh

proc Numerate {fileName} {
set h [open $fileName r]
set lineNumber 0
while {[gets $h line] >= 0} {
incr lineNumber
puts ">SEQUENCE_${lineNumber}_length_35"
puts $line
}
close $h
}

if {$argc >= 1} {
Numerate [lindex $argv 0]
} else {
puts "Usage: tclsh script.tcl filename"
}

если сделать скрипту chmod +x, то по идее запустится просто: ./script.tcl myfile.txt
в вашем случае запуск такой:
./script.tcl forSOAP_s7_final.fa > s7_fasted.fa

artimon

perl -pe 'print ">SEQUENCE_", ++$i, "_length_35\n"' < s7.fa

Anturag

 
 % i=1; cat forSOAP_s7_final.fa | while read line; do echo '>SEQUENCE_'${i}'_length_35'; echo $line; i=$i+1; done > s7_fasted.fa

Xomiak09

Всем большое спасибо!

banderon

Ну и на sed'е, раз уж просили :grin:

sed -e "=" | sed -e "s/^/>SEQUENCE_/;s/$/_length_35/;N"

banderon

Решил ещё сравнить по скорости предложенные решения
Тестировались на одном файле в 1млн строк. Результаты сравнивались, у всех получалось одно и то же :)























scriptrealusersys
_script.tcl12.486s6.252s4.213s
_perl5.047s2.043s0.194s
_bash1m57.362s1m28.694s16.965s
_sed6.012s4.159s0.294s
_awk4.887s1.793s0.194s
_haskell_wine1m25.286s34.061s14.562s


Самые быстрые пока perl и awk. В решении похоже где-то вылазит квадратичное время работы, или просто константа большая при n :confused:

Vladu

awk
awk '{print "SEQUENCE_" NR "_length_35"} 1'  

Maurog

а давай еще в эту статистику вот это чудо вставим?:)

import System (getArgs)

parseFile :: String -> IO
parseFile filename = do
content <- readFile filename
mapM_ putStrLn $ map (\(x, y) -> concat [">SEQUENCE_", show x, "_length_35\n", y]) $ zip [1..] (lines content)

main = do
args <- getArgs
case args of
[] -> error "Usage: program filename"
(filename:xs) -> parseFile filename

banderon

Не, не получится, я либо не знаю, что это за язык, либо у меня к нему интерпретатора нет на компе. А скорее всего ни то, ни другое :grin:

doublemother

пейтон это

alfadred

пейтон это
Это не пейтон, это Haskell.

Maurog

Не, не получится
если ты на винде, то я тебе могу дать, должен запуститься без доп. либ
зы: возможно, это уже нечестно сравнивать со скомпилированным скриптом =\

alfadred

зы: возможно, это уже нечестно сравнивать со скомпилированным скриптом =\
Это да, чтобы по-честному, надо через runghc запускать.

Maurog

Это да, чтобы по-честному, надо через runghc запускать.
вот спасибо, а я не знал=\
ковырял командную строчку у ghc, ghci и ничего не нашел =\

banderon

зы: возможно, это уже нечестно сравнивать со скомпилированным скриптом =\
С моей стороны тоже будет нечестно запускать его через wine :p
Добавил строчку в табличку

Maurog

что-то барахлит твой скрипт
можешь подфиксить?

Maurog

Аналогичная статистика (cygwin на помощь пришел)






































script real user sys
_perl 0m2.884s 0m2.609s 0m0.202s
_awk 0m3.385s 0m3.328s 0m0.031s
_bash 2m34.265s 1m24.561s 1m18.983s
_script.tcl 0m29.753s 0m0.000s 0m0.046s
_hs 0m5.834s 0m0.000s 0m0.016s
_hs_exe 0m3.567s 0m0.000s 0m0.000s
_bat 34.23m
_vbs 0m43.249s 0m0.015s 0m0.000s
_lua 0:02.89
hat_if_nat (37%) 631m24.843s 122m34.159s 248m2.638s
_ocaml 0:12.07

pitrik2

Решил ещё сравнить по скорости предложенные решения
эээ
а можно изначальный скрипт тож в таблицу сравнения добавить?
ну и результаты тоже сравнить :)

Maurog

а можно изначальный скрипт тож в таблицу сравнения добавить?
ну и результаты тоже сравнить
ты издеваешься, да ? :grin:
и за трое суток скрипт не успел обработать и 20 % инфы

pitrik2

и за трое суток скрипт не успел обработать и 20 % инфы
дык на его данных
я вот не уверен что у такие же данные

apl13

awk был?
awk '{print ">SEQUENCE_" ++cnt "_length_35\n" $0}' forSOAP_s7_final.fa > s7_fasted.fa

margadon

фу!
есть же NR

apl13

Бля, палюсь. :crazy:

doublemother

ocaml
let rec process ch i =
let s = input_line ch in
print_endline (String.concat "" (">SEQUENCE_" :: string_of_int i :: "_length_35" :: [];
print_endline s;
process ch (i+1);
;;
try
process stdin 1;
with End_of_file -> ;;

apl13

awk '{print ">SEQUENCE_" NR "_length_35\n" $0}' forSOAP_s7_final.fa > s7_fasted.fa

apl13

Или даже
awk '{print ">SEQUENCE_" NR "_length_" length($0) "\n" $0}' forSOAP_s7_final.fa > s7_fasted.fa

Maurog

баяните, мистер :grin:

apl13

Однако меня несколько смущает имя входного файла. Наше мыло настолько сурово, что его уже делают из нуклеиновых кислот? :spy:

apl13

selffix после того, как все видели. :crazy:

apl13

А чтоб искупить свою вину кровью, сейчас на брейнфаке напишу. :bat:

karkar

Ocaml покороче:
open ExtLib;;
Enum.iteri (fun i s -> Printf.printf ">SEQUENCE_%d_length_35\n%s\n" (i+1) s) (Std.input_lines stdin);;

margadon

А чтоб искупить свою вину кровью, сейчас на брейнфаке напишу
чьей кровью?! :o

erotic

В решении похоже где-то вылазит квадратичное время работы, или просто константа большая при n :confused:
Интересно, где косяк-то. Нередко приходится read'ом пользоваться.
Оставить комментарий
Имя или ник:
Комментарий: