LINUX.ORG.RU
ФорумAdmin

Добавить переносы строки


0

2

Есть длинная строка более 30 мб, вида:
dsdkfjkjdf<NN>adslklksdf<NN>kdljljsd<NN>odsklkldfsklfg><NN>kjkjlkjsdal
На вот такую команду:
echo «dsdkfjkjdf<NN>adslklksdf<NN>kdljljsd<NN>odsklkldfsklfg><NN>kjkjlkjsdal» | sed 's/<NN>/^M<NN>/g'
в рузультате только:
<NN>kjkjlkjsdallfg>
А нужно чтобы набор символов начинающийся с <NN> был с новой строки. Как быть?


что такое ^M?! операционкой не ошибся? здесь это называется \n

aol ★★★★★ ()
$ echo "dsdkfjkjdf<NN>adslklksdf<NN>kdljljsd<NN>odsklkldfsklfg><NN>kjkjlkjsdal" | sed 's/<NN>/\n<NN>/g'
dsdkfjkjdf
<NN>adslklksdf
<NN>kdljljsd
<NN>odsklkldfsklfg>
<NN>kjkjlkjsdal
arsi ★★★★★ ()

А нужно чтобы набор символов начинающийся с <NN> был с новой строки. Как быть?

можно создать файл сл. содержания:

#!/bin/sed -f 
s/<NN>/
&/g

Насколько я помню, так должно работать везде.

drBatty ★★ ()
Ответ на: комментарий от drBatty

Блин, а как он долго это делает с 30 Мб файлом... :-((( Несколько минут... При том, что tr (правда с заменой всего одного символа (несколько символов не может) на новую строку делает это за несколько секунд. Надо perl чтоль для этого приспосабливать?

Viper ()
Ответ на: комментарий от Viper

>Блин, а как он долго это делает с 30 Мб файлом... :-((( Несколько минут... При том, что tr (правда с заменой всего одного символа (несколько символов не может) на новую строку делает это за несколько секунд. Надо perl чтоль для этого приспосабливать?

попробуйте gawk, дело в том, что тут надо работать с мелкими записями, а не с одной огромной задачей. sed заточена на обработку текста с мелкими строчками (~50-100 байт), причём строки обязательно должны разделятся \n. А вот gawk способна обработать любые записи, в т.ч. и «строчки», где разделитель не \n, а произвольное RE.

ЕМНИП в перловке таже беда что и в sed.

(вот только я не знаю, может-ли это простая, не гнутая awk).

drBatty ★★ ()
Ответ на: комментарий от drBatty

> ЕМНИП в перловке таже беда что и в sed.

смотря как готовить ;)

немножко не то, что требовалось:

$ echo "dsdkfjkjdf<NN>adslklksdf<NN>kdljljsd<NN>odsklkldfsklfg><NN>kjkjlkjsdal" | perl -pe 'BEGIN{$/="<NN>";$\="\n"}'
dsdkfjkjdf<NN>
adslklksdf<NN>
kdljljsd<NN>
odsklkldfsklfg><NN>
kjkjlkjsdal

то, что хотел автор:

$ echo "dsdkfjkjdf<NN>adslklksdf<NN>kdljljsd<NN>odsklkldfsklfg><NN>kjkjlkjsdal" | perl -pe 'BEGIN{$/="<NN>"} s/<NN>$/\n<NN>/'
dsdkfjkjdf
<NN>adslklksdf
<NN>kdljljsd
<NN>odsklkldfsklfg>
<NN>kjkjlkjsdal

хотя хз, бенчмарков не делал ^^

arsi ★★★★★ ()
Ответ на: комментарий от arsi
doc@dt:~/docs/scripts$ time -p perl -pe 'BEGIN{$/="<NN>"} s/<NN>$/\n<NN>/' < big.txt >/dev/null
real 8.17
user 5.39
sys 0.05
doc@dt:~/docs/scripts$ time -p perl -pe 'BEGIN{$/="<NN>"} s/<NN>$/\n<NN>/' < big.txt >/dev/null
real 8.34
user 5.44
sys 0.05
doc@dt:~/docs/scripts$ time -p perl -pe 'BEGIN{$/="<NN>"} s/<NN>$/\n<NN>/' < big.txt >/dev/null
real 8.34
user 5.30
sys 0.06
doc@dt:~/docs/scripts$ time -p sed 's/<NN>/\n&/g' big.txt >/dev/null
real 2.74
user 1.44
sys 0.02
doc@dt:~/docs/scripts$ time -p sed 's/<NN>/\n&/g' big.txt >/dev/null
real 2.18
user 1.45
sys 0.02
doc@dt:~/docs/scripts$ time -p sed 's/<NN>/\n&/g' big.txt >/dev/null
real 2.77
user 1.47
sys 0.02
doc@dt:~/docs/scripts$ ls -lh big.txt 
-rw-r--r-- 1 doc users 33M 2010-12-23 16:33 big.txt

Вывод - perl хуже.

тестовый файл - повторённое кучу раз <NN>adslklksdf

drBatty ★★ ()
Ответ на: комментарий от Viper

у вас памяти хватило? почему-то результаты очень разные - у меня секунды, у вас минуты. может вы искали не <NN>? А что-нить вроде <(b)>[^<]*<\1> ? В любом случае, для значительного ускорения можно использовать POSIX локаль, тогда sed работает как perl, с байтами а не символами в UTF-8 (размер символов считать не нужно, они все по 1 байту)

drBatty ★★ ()
Ответ на: комментарий от drBatty

мда, я недооценивал скорость работы регекспов перла на больших данных :)

perl -pe 's/<NN>/\n<NN>/g'

работает примерно с той же скоростью, что и sed. лишние костыли не нужны.

arsi ★★★★★ ()
Ответ на: комментарий от drBatty

У меня немного посложнее ищется <NN[0-9][0-9]> и заменяется на перенос строки и такой же номер NN. Может быть по этому.

Viper ()

На awk, которая под Linux, быстрее всего получается: awk '{gsub(«<NN[0-9][0-9]?>», «\n&1»); print}' Но под Solaris это не проходит.

Viper ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.