The OpenNET Project / Index page

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




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Bash sed: расстановка отступов для уровней вложенности, !*! OzalexO, 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 и перебор в цикле делать умею, но это медленно.

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

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

    • Bash sed: расстановка отступов для уровней вложенности, !*! OzalexO, 15:48 , 26-Дек-08 (3)
      >Если 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
      -------------------------------------------------------------------------

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

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

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

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

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

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

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

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

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

      • о времена..., !*! OzalexO, 16:00 , 26-Дек-08 (5)
        Да, про "---^^" не совсем понятно...


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

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

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

        Хреновое резюме. Если чтение четырёх строк вызывает затруднения (мне 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 не медленнее. оплата - в кассу!, !*! Andrey Mitrofanov, 12:26 , 30-Дек-08 (9)
    >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

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

      • С Новым Годом! :), !*! OzalexO, 17:57 , 31-Дек-08 (11)

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

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




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

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