2016-08-02 3 views
0

Я делаю завиток в XML-файле. Выход, как:parse output like id: name/class: id to id: class: name with bash awk

name 
    uuid3 - name 
    uuid1 - name 
    uuid2 - name 
class 
    class - uuid3 
    class - uuid2 
    class - uuid1 

Мне нужно сортировать эту модель, как:

uuid1 - class - name 
uuid2 - class - name 
uuid3 - class - name 

Я думаю, что лучший способ сделать материал awk, но все решения хороши.

спасибо большое.

+2

У вас есть код? – Nunchy

+0

Вы правы, awk - лучший способ сделать это. Прочтите книгу «Эффективное программирование Awk», 4-е издание, Арнольд Роббинс, чтобы начать. –

ответ

4

awk на помощь!

$ awk 'BEGIN{OFS=FS=" - "} 
      {gsub(/ /,"",$1); gsub(/ /,"",$2)} 
     c==1{a[$1]=$2} 
     c==2{print $2,$1,a[$2]} 
     NF==1{c++}' file 

uuid3 - class - name 
uuid2 - class - name 
uuid1 - class - name 

порядок заявок основан на втором блоке.

Объяснение

«с» является счетчиком блока, увеличивается, когда есть только одно поле (заголовок). При обработке первого блока (c==1) он создает карту (массив awk) для связывания полей один и два. Во второй обработке блока (c==2) печатает второе поле, первое поле и просматривает значение из карты для первого поля. Первый раздел кода удаляет лишние пробелы для поиска.

+0

Гораздо более красноречиво, чем мое решение. – Nunchy

+0

waow <3 thx много – Moker

+0

Не могли бы вы подробно объяснить мне, что строки: c == 1 {a [$ 1] = $ 2}, c == 2 {print a [$ 2], $ 1, $ 2}, NF == 1 {C++}? благодаря – Moker

0

Предполагая «класса» буквальной константы, и мы можем использовать его в качестве эталона, то это будет работать:

#!/bin/bash 

str=" 
name 
    uuid1 - one 
    uuid2 - two 
    uuid3 - three 
class 
    class - uuid1 
    class - uuid2 
    class - uuid3 
" 

# Get all lines where the first token is 'class' 
class=`echo -e "${str}" | grep -P "\tclass"` 

# Count all of the lines... 
lines=`echo -e "${class}" | wc -l` 

echo -e "lines = ${lines}\n" 

strout= 

# Loop through the result and extract each individual line... 
l=1 
while [ $l -le $lines ]; do 
    line=`echo -e "${class}" | head -n ${l} | tail -n 1` 

    # Now, token 3 will be the unique uuid token... 
    uuid=`echo -e "$line" | awk '{print $3}'` 

    # We can use this unique uuid to reference the name lines... 
    n=`echo -e "${str}" | grep -P "\t$uuid" | awk '{print $3}'` 

    strout="${strout}\n${uuid} - class - ${n}" 

    l=$((l+1)) 
done 

echo -e "${strout}" 

Если «класс» не является символьной строка, она все еще может быть некоторая помощь. К сожалению, вы не указали много информации в OP