The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Bash sed: расстановка отступов для уровней вложенности"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [ Отслеживать ]

"Bash sed: расстановка отступов для уровней вложенности"  
Сообщение от OzalexO email(ok) on 26-Дек-08, 14:22 
Добрый день,

Есть исходный файл такого типа:

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 и перебор в цикле делать умею, но это медленно.

Высказать мнение | Ответить | Правка | Cообщить модератору

 Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Bash sed: расстановка отступов для уровней вложенности"  
Сообщение от phpcoder email(??) on 26-Дек-08, 15:08 
>awk и перебор в цикле делать умею, но это медленно.

Как-то не верится даже. Если awk медленный, то и sed IMHO не будет быстрее.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

3. "Bash sed: расстановка отступов для уровней вложенности"  
Сообщение от OzalexO email(ok) on 26-Дек-08, 15:48 
>Если awk медленный, то и sed IMHO не
>будет быстрее.

Ниже весь мой скрипт.
Первая часть ('sed') отрабатывает за 10 секунд,
а вторая ('while') за две минуты, при исходном файле в 20 тыс строк.

Поэтому я предполагаю, что редактирование файла только через sed будет быстрее.


-------------------------------------------------------------------------------
#!/bin/bash

FILE=$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.os

startout=`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.message

endscr=`date`" : Script finished"

echo $startpar
echo $startout
echo $endscr
-------------------------------------------------------------------------

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

6. "Bash sed: расстановка отступов для уровней вложенности"  
Сообщение от vic (??) on 26-Дек-08, 17:56 
т.е. вот это будет медленно?

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к строк ушло меньше секунды.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

2. "о времена..."  
Сообщение от Andrey Mitrofanov on 26-Дек-08, 15:43 
Вас в школе не научили решать задачи? ...выбирать интсрумент для и решать? ...оценивать результаты (в т.ч. и промежуточные) и менять постановку задачи, если требуется? Или теперь задачками "про sed" воспитательницы дет.садов мучают "цветы жизни"?...

>Подскажите плиз, как такое можно сделать?

Читать info sed. Много долго думать...
Пытаться написать конструкцию...
Долго танцевать вокруг hold и pattern space-ов.
Повторять---^^ до полного удовлетворения.

Ну, я сделал для собственного упражнения этот скрипт.
У меня работает -- я в Вас верю, Вас всё получится.

>awk и перебор в цикле делать умею, но это медленно.

Сделай на перле, если быстрее будет...... Ещё, говорят, Си - "быыыстрый" язык.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

4. "о времена..."  
Сообщение от OzalexO email(ok) on 26-Дек-08, 15:59 
Резюмируем написанное: "кури ман" )))
Спасибо, уже курю параллельно.

А за пример или хотя описание принципа работы sed для данного конкретного случая скажу отдельную спасибу.

На перле низя, ибо нету, а на си нежелательно, ибо надо будет иногда скрипт менять ( и не только мне, поэтому с исходниками и компиляцией возиться неудобно ).

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

5. "о времена..."  
Сообщение от OzalexO email(ok) on 26-Дек-08, 16:00 
Да, про "---^^" не совсем понятно...


Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

7. "о времена..."  
Сообщение от Pahanivo email(ok) on 26-Дек-08, 18:34 
>Резюмируем написанное: "кури ман" )))
>Спасибо, уже курю параллельно.
>
>А за пример или хотя описание принципа работы sed для данного конкретного
>случая скажу отдельную спасибу.
>
>На перле низя, ибо нету, а на си нежелательно, ибо надо будет
>иногда скрипт менять ( и не только мне, поэтому с исходниками
>и компиляцией возиться неудобно ).

это чеж за платформа где перла нет? ))

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

8. "обсудим философские аспекты"  
Сообщение от Andrey Mitrofanov on 26-Дек-08, 18:44 
>Резюмируем написанное: "кури ман" )))

Хреновое резюме. Если чтение четырёх строк вызывает затруднения (мне 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

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

9. "бенчмарк. awk не медленнее. оплата - в кассу!"  
Сообщение от Andrey Mitrofanov on 30-Дек-08, 12:26 
>awk и перебор в цикле делать умею, но это медленно.

А я сумел сделать на sed-е и это медленнее, чем на awk-е (сравнивал с реализацией vlc из реплики #6)

Итак. Входные данные - два "тестовых набора" (первый - попроще, второй - сильно вложенный) с разным количеством строк. Тестируемые скрипты (четыре)- мой на sed (без расширения; запускался под GNU sed) и .awk от vlc, запускаемый под gawk "как awk", под gawk "как gawk" и под nawk.

Вывод: awk не медленнее sed-а. Проверявшаяся реализация скрипта и на проверявшихся реализациях интерпретаторов -- по крайней мере.

ПРИЛОЖЕНИЕ 1, прОтокол.

$ cat ./BM.sh
#!/bin/bash

data0() { 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

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

10. "С Новым Годом! :)"  
Сообщение от Andrey Mitrofanov on 31-Дек-08, 17:22 
>Тестируемые скрипты (четыре)- мой на
>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 -f

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);
}
$ head -1 ./indent.*
==> ./indent.awk <==
#!/usr/bin/awk -f

==> ./indent.gawk <==
#!/usr/bin/gawk -f

==> ./indent.nawk <==
#!/usr/bin/nawk -f
$ exit

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

11. "С Новым Годом! :)"  
Сообщение от OzalexO (ok) on 31-Дек-08, 17:57 

>$SUBJ Уж не знаю, потянет ли на Подарок , но вот: "индентер"
>на sed-е и проч.мелочи. +<:)

С Новым Годом! На Подарок точно тянет! Спасибо! И отдельная "большая спасиба" в кассу!
Будет мне подспорье в изучении info sed. И еще вкусности... Выходные продут очень продуктивно.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Спонсоры:
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2021 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру