Добрый день,Есть исходный файл такого типа:
start
message1
start
message2
start
message3
end
end
message4
start
message5
end
endНадо только с помощью sed переформатировать его в такой формат:
start
message1
start
message2
start
message3
end
end
message4
start
message5
end
endТ.е. дополнить строки пробелами в зависимости от уровня вложения.
Я пробовал сделать как-то так, но это, естественно, не работает:
sed -n '
/.*start/ { #если в текущей строке найде start
N # то берем следующую строку
/.*stop/! { #и если она не end
s/^/ /p #добавляем пару пробелов в начало
}
}
' testПодскажите плиз, как такое можно сделать? awk и перебор в цикле делать умею, но это медленно.
>awk и перебор в цикле делать умею, но это медленно.Как-то не верится даже. Если awk медленный, то и sed IMHO не будет быстрее.
>Если awk медленный, то и sed IMHO не
>будет быстрее.Ниже весь мой скрипт.
Первая часть ('sed') отрабатывает за 10 секунд,
а вторая ('while') за две минуты, при исходном файле в 20 тыс строк.Поэтому я предполагаю, что редактирование файла только через sed будет быстрее.
-------------------------------------------------------------------------------
#!/bin/bashFILE=$1
grep '.' $FILE > $FILE.os
startpar=`date`" : Start parsing"
sed -n '
/APP-TRACE/ {
/time:[[{][0-9][0-9]:[0-9][0-9]:[0-9][0-9][:\.][0-9][0-9][0-9][]}]/ {
H
x
s/.*time:[[{]\([0-9][0-9]:[0-9][0-9]:[0-9][0-9][:\.][0-9][0-9][0-9]\)[]}].*/\1/w '$FILE.time'
x
}
/time:[[{][0-9][0-9]:[0-9][0-9]:[0-9][0-9][:\.][0-9][0-9][0-9][]}]/! {
H
x
s/.*/............./
w '$FILE.time'
x
}
/processname:\"[A-Za-z0-9_]\+\"/ {
H
x
s/.*processname:\"\([A-Za-z0-9_]\+\)\".*/\1/w '$FILE.procname'
x
}
/processname:\"[A-Za-z0-9_]\+\"/! {
H
x
s/.*/............./
w '$FILE.procname'
x
}
/Method:\"[A-Za-z0-9_]\+\"/ {
H
x
s/.*Method:\"\([A-Za-z0-9_]\+\)\".*/\1/w '$FILE.method'
x
}
/Method:\"[A-Za-z0-9_]\+\"/! {
H
x
s/.*/............./
w '$FILE.method'
x
}
/Message:\"[^\"]\+/ {
H
x
s/.*Message:\"\([^\"]\+\).*/\1/w '$FILE.message'
x
}
/Message:\"[^\"]\+/! {
H
x
s/.*/............./
w '$FILE.message'
x
}
H
x
s/.*//
w '$FILE.other'
x
}
/APP-TRACE/! {
w '$FILE.other'
s/.*//
w '$FILE.time'
w '$FILE.procname'
w '$FILE.method'
w '$FILE.message'
}
' $FILE.osstartout=`date`" : Start output"
maxProcNameLength=`wc -L $FILE.procname|sed 's/^\([0-9]\+\) .*/\1/'`
maxMethodLength=`wc -L $FILE.method|sed 's/^\([0-9]\+\) .*/\1/'`
maxLength=`expr 13 + $maxProcNameLength + $maxMethodLength`curLevel=0
while read fOther <&1
do
read fTime <&2
read fProcName <&3
read fMethod <&4
read fMessage <&5
if [ "$fMessage" == "starts {" ]
then
curLevel=`expr $curLevel +2`
fMessage=""
fMethod="$fMethod {"
echo "START: $curLevel"
else
if [ "$fMessage" == "ends }" ]
then
fMessage=""
fMethod="$fMethod }"
if [ $curLevel -ne 0 ]
then
curLevel=`expr $curLevel - 2`
fi
echo "END: $curLevel"
else
subLevel=`expr $curLevel + 2`
fi
fi
awk -v s1="$fOther" -v s2="$fTime" -v s3="$fProcName" -v s4="$fMethod" -v s5="$fMessage" \
'BEGIN {if(length(s1) == 0) { \
printf "%-13s%-'${maxProcNameLength}'s :: %-'${curLevel}'s%-'${maxMethodLength}'s | %s\n", s2, s3, " ", s4, s5 } \
else \
print s1 \
}' >> $FILE.atr
done 1<$FILE.other 2<$FILE.time 3<$FILE.procname 4<$FILE.method 5<$FILE.messageendscr=`date`" : Script finished"
echo $startpar
echo $startout
echo $endscr
-------------------------------------------------------------------------
т.е. вот это будет медленно?awk 'BEGIN { t = "" } {
if ($1 == "start") { printf("%s%s\n", t, $0); t = t " "; }
else if ($1 == "end") { t = substr(t, 3); printf("%s%s\n", t, $0); }
else printf("%s%s\n", t, $0);
}' < mega.txtв виртуалке на 300к строк ушло меньше секунды.
Вас в школе не научили решать задачи? ...выбирать интсрумент для и решать? ...оценивать результаты (в т.ч. и промежуточные) и менять постановку задачи, если требуется? Или теперь задачками "про sed" воспитательницы дет.садов мучают "цветы жизни"?...>Подскажите плиз, как такое можно сделать?
Читать info sed. Много долго думать...
Пытаться написать конструкцию...
Долго танцевать вокруг hold и pattern space-ов.
Повторять---^^ до полного удовлетворения.Ну, я сделал для собственного упражнения этот скрипт.
У меня работает -- я в Вас верю, Вас всё получится.>awk и перебор в цикле делать умею, но это медленно.
Сделай на перле, если быстрее будет...... Ещё, говорят, Си - "быыыстрый" язык.
Резюмируем написанное: "кури ман" )))
Спасибо, уже курю параллельно.А за пример или хотя описание принципа работы sed для данного конкретного случая скажу отдельную спасибу.
На перле низя, ибо нету, а на си нежелательно, ибо надо будет иногда скрипт менять ( и не только мне, поэтому с исходниками и компиляцией возиться неудобно ).
Да, про "---^^" не совсем понятно...
>Резюмируем написанное: "кури ман" )))
>Спасибо, уже курю параллельно.
>
>А за пример или хотя описание принципа работы sed для данного конкретного
>случая скажу отдельную спасибу.
>
>На перле низя, ибо нету, а на си нежелательно, ибо надо будет
>иногда скрипт менять ( и не только мне, поэтому с исходниками
>и компиляцией возиться неудобно ).это чеж за платформа где перла нет? ))
>Резюмируем написанное: "кури ман" )))Хреновое резюме. Если чтение четырёх строк вызывает затруднения (мне B-) часто говорят, что не врубаются, что я говорю), вот одной строкой:
Читать инфо, чтобы врубиться в ограничения языка и, учитывая ограниченные средства, подходить к задаче.
%-) Боюсь одна получилась длиннее четырёх... Судьба!
>А за пример или хотя описание принципа работы sed для данного конкретного
>случая скажу отдельную спасибу.""Долго танцевать вокруг hold и pattern space-ов.""
>ибо надо будет иногда скрипт менять ( и не только мне
За скрипт _такой_ сложности на sed (*1) "другие" могут и побить. Матом вспомнят точно: при каждой попытке изменить. :-/ (*3)
---
>Да, про "---^^" не совсем понятно...Это, типа, стрелочка. В смысле "повторять то, что написано выше, до полного".
---
(*1) у меня получилось ажно 15 (примерно: считая "адреса"-регекспы, не считая пустых строк и комментариев) команд "жонглирующих" hold-ом:
$ wc indent
14 21 115 indent
$ cat indent|tr \\n \;|sed 's/[ {}]//g;s/\\\;/+/g'|tr \; \\n|sed -n '/^#/n;/^$/n;p'|wc -l
15
$ _(*2) Так как _у_меня_ долго думание с чтением инфотекста случилось несколько ранее, то попытки написать +чтение инфотекста +попытки жонглирования заняли примерно -
-rwxr--r-- 1 user user 115 2008-12-26 15:32 indent
-rw-r--r-- 1 user user 85 2008-12-26 14:41 txt
- _51_ минуту и потребовали, кроме того, некоторого креативного состояния духа. Ещё [чуть больше] времени я потратил на написание своих ответов в этой теме. По пути написал "бенчмарк" и погонял его на своей реализации, погрел стоящий передо мной "Intel(R) Pentium(R) 4 CPU 2.66GHz", могу результаты показать -- они ничего не стоят.(*3)Есть, правда выход: комментировать всесторонне и всеохватывающе, тогда, возможно, чтение комментариев на нескольких страницах(*4) к скрипту в полтора десятка строк, предотвратит чрезмерную :) реакцию.
(*4)
Этот текст -- all rights reserved, исключительно для OpenNET (c) 2008, Andrey Mitrofanov
>awk и перебор в цикле делать умею, но это медленно.А я сумел сделать на sed-е и это медленнее, чем на awk-е (сравнивал с реализацией vlc из реплики #6)
Итак. Входные данные - два "тестовых набора" (первый - попроще, второй - сильно вложенный) с разным количеством строк. Тестируемые скрипты (четыре)- мой на sed (без расширения; запускался под GNU sed) и .awk от vlc, запускаемый под gawk "как awk", под gawk "как gawk" и под nawk.
Вывод: awk не медленнее sed-а. Проверявшаяся реализация скрипта и на проверявшихся реализациях интерпретаторов -- по крайней мере.
ПРИЛОЖЕНИЕ 1, прОтокол.
$ cat ./BM.sh
#!/bin/bashdata0() { yes start|head -$1 ;echo message; yes end|head -$1; }
data201() { for(( i=$1; i>0; i-=201)); do data0 $((i>201?100:i/2)); done; }dataMAX() { yes start|head -$(($1/2)) ;echo message; yes end|head -$(($1/2)); }
BM() { echo "$3 `$2 $3 | time ./$1 2>&1 >/dev/null \
|awk '/elapsed/{print $1" "$4((gensub(/:/,"",1,$3)+0>3)?" "$3:"")}' `"; }for scr in indent indent.awk indent.gawk indent.nawk; do
echo "*** $scr, data201"
for n in 1 10 100 1000 `seq 10000 10000 100000`; do
BM $scr "data201" $n
done
echo "*** $scr, dataMAX"
for n in 1 10 100 `seq 1000 1000 10000`; do
BM $scr "dataMAX" $n
done
done
$ ./BM.sh
*** indent, data201
1 0.00user 0%CPU
10 0.00user 0%CPU
100 0.00user 17%CPU
1000 0.04user 32%CPU
10000 0.54user 43%CPU
20000 1.04user 43%CPU
30000 1.78user 49%CPU
40000 2.20user 46%CPU 0:04.81elapsed
50000 2.82user 45%CPU 0:06.22elapsed
60000 3.18user 31%CPU 0:10.03elapsed
70000 3.69user 43%CPU 0:08.43elapsed
80000 4.42user 43%CPU 0:10.23elapsed
90000 4.78user 32%CPU 0:14.65elapsed
100000 5.70user 31%CPU 0:17.96elapsed
*** indent, dataMAX
1 0.00user 0%CPU
10 0.00user 0%CPU
100 0.00user 28%CPU
1000 0.26user 70%CPU
2000 0.92user 92%CPU
3000 2.06user 64%CPU
4000 3.88user 69%CPU 0:05.58elapsed
5000 6.30user 96%CPU 0:06.55elapsed
6000 8.04user 77%CPU 0:10.37elapsed
7000 12.66user 87%CPU 0:14.44elapsed
8000 14.28user 95%CPU 0:14.92elapsed
9000 19.65user 91%CPU 0:21.48elapsed
10000 22.93user 95%CPU 0:23.96elapsed
*** indent.awk, data201
1 0.00user 0%CPU
10 0.00user 0%CPU
100 0.00user 36%CPU
1000 0.00user 3%CPU
10000 0.03user 4%CPU
20000 0.07user 5%CPU
30000 0.07user 4%CPU
40000 0.12user 5%CPU
50000 0.18user 5%CPU
60000 0.20user 4%CPU 0:04.06elapsed
70000 0.30user 5%CPU 0:05.41elapsed
80000 0.29user 5%CPU 0:05.57elapsed
90000 0.29user 4%CPU 0:07.14elapsed
100000 0.36user 5%CPU 0:07.36elapsed
*** indent.awk, dataMAX
1 0.00user 61%CPU
10 0.00user 0%CPU
100 0.00user 28%CPU
1000 0.00user 25%CPU
2000 0.00user 16%CPU
3000 0.01user 51%CPU
4000 0.02user 77%CPU
5000 0.03user 91%CPU
6000 0.03user 63%CPU
7000 0.04user 70%CPU
8000 0.06user 81%CPU
9000 0.07user 85%CPU
10000 0.08user 89%CPU
*** indent.gawk, data201
1 0.00user 0%CPU
10 0.00user 0%CPU
100 0.00user 0%CPU
1000 0.00user 11%CPU
10000 0.04user 7%CPU
20000 0.09user 7%CPU
30000 0.12user 6%CPU
40000 0.13user 5%CPU
50000 0.15user 4%CPU
60000 0.19user 4%CPU 0:05.02elapsed
70000 0.19user 3%CPU 0:06.39elapsed
80000 0.26user 4%CPU 0:06.33elapsed
90000 0.27user 3%CPU 0:07.65elapsed
100000 0.35user 4%CPU 0:07.96elapsed
*** indent.gawk, dataMAX
1 0.00user 0%CPU
10 0.00user 21%CPU
100 0.00user 0%CPU
1000 0.00user 16%CPU
2000 0.00user 30%CPU
3000 0.01user 47%CPU
4000 0.03user 68%CPU
5000 0.03user 81%CPU
6000 0.04user 77%CPU
7000 0.06user 86%CPU
8000 0.06user 39%CPU
9000 0.08user 52%CPU
10000 0.10user 42%CPU
*** indent.nawk, data201
1 0.00user 9%CPU
10 0.00user 26%CPU
100 0.00user 25%CPU
1000 0.00user 2%CPU
10000 0.03user 3%CPU
20000 0.05user 2%CPU
30000 0.11user 2%CPU
40000 0.10user 3%CPU 0:04.17elapsed
50000 0.18user 5%CPU
60000 0.19user 4%CPU 0:04.98elapsed
70000 0.20user 3%CPU 0:05.80elapsed
80000 0.28user 4%CPU 0:06.26elapsed
90000 0.26user 3%CPU 0:07.40elapsed
100000 0.33user 4%CPU 0:08.11elapsed
*** indent.nawk, dataMAX
1 0.00user 0%CPU
10 0.00user 0%CPU
100 0.00user 0%CPU
1000 0.00user 27%CPU
2000 0.01user 48%CPU
3000 0.01user 48%CPU
4000 0.02user 47%CPU
5000 0.03user 70%CPU
6000 0.04user 75%CPU
7000 0.04user 68%CPU
8000 0.04user 64%CPU
9000 0.08user 97%CPU
10000 0.09user 86%CPU
$ exit
>Тестируемые скрипты (четыре)- мой на
>sed (без расширения; запускался под GNU sed) и .awk от vlc,
>запускаемый под gawk "как awk", под gawk "как gawk" и под
>nawk.$SUBJ Уж не знаю, потянет ли на Подарок , но вот: "индентер" на sed-е и проч.мелочи. +<:)
$ ls -l indent
-rwxr--r-- 1 abm abm 115 2008-12-26 15:32 indent
$ cat ./indent
#!/bin/sed -f/end/{
x; s/ $//; x
}
x;G;s/\
/:/;h
s/:.\+$//
x
s/^\( *\):/\1/
#p
/start/{
x; s/$/ /; x
}
$ ls -l indent.*
-rwxr--r-- 1 abm abm 208 2008-12-26 18:47 indent.awk
-rwxr--r-- 1 abm abm 209 2008-12-30 10:37 indent.gawk
-rwxr--r-- 1 abm abm 209 2008-12-29 11:27 indent.nawk
$ cat ./indent.gawk
#!/usr/bin/gawk -fBEGIN { t = "" } {
if ($1 == "start") { printf("%s%s\n", t, $0); t = t " "; }
else if ($1 == "end") { t = substr(t, 3); printf("%s%s\n", t, $0); }
else printf("%s%s\n", t, $0);
}
$ head -1 ./indent.*
==> ./indent.awk <==
#!/usr/bin/awk -f==> ./indent.gawk <==
#!/usr/bin/gawk -f==> ./indent.nawk <==
#!/usr/bin/nawk -f
$ exit
>$SUBJ Уж не знаю, потянет ли на Подарок , но вот: "индентер"
>на sed-е и проч.мелочи. +<:)С Новым Годом! На Подарок точно тянет! Спасибо! И отдельная "большая спасиба" в кассу!
Будет мне подспорье в изучении info sed. И еще вкусности... Выходные продут очень продуктивно.