форматирование с awk

У меня есть этот текст:

Core/Dev
Core/master
FrontEnd/Dev
FrontEnd/DoubleClick
FrontEnd/HEAD -> FrontEnd/master
FrontEnd/master
Infrastructure/Dev
Infrastructure/master
Software/Dev
Software/Control
Software/master

Я хочу достигнуть этого:

Core:Dev,master
FrontEnd:Dev,DoubleClick,master
Infrastructure:Dev,master
Software:Dev,Control,master

Заметьте все строки с тем же, запуск объединен, и значения являются запятой-seperated,

и строка с HEAD проигнорирован.

Что лучший способ состоит в том, чтобы сделать это, sed или awk?еще как?Спасибо.

3
задан 6 July 2016 в 15:48

4 ответа

Получил ответ! Благодарите всех в течение своего времени

awk '
    # split remote and branch
    {
        remote = substr($1, 0, index($1, "/") - 1)
        branch = substr($1, index($1, "/") + 1)
    }

    # eliminate HEAD reference
    branch == "HEAD" { next }

    # new remote found
    remote != lastRemote {
        # output remote name
        printf "%s%s:", lastRemote ? "\n" : "", remote
        lastRemote = remote
        # do not output next comma
        firstBranch = 1
    }

    # output comma between branches
    !firstBranch { printf "," }
    firstBranch { firstBranch = 0 }

    # output branch name
    { printf branch }

    # final linebreak
    END { print "" }
'
0
ответ дан 1 December 2019 в 15:54

Вы могли выполнить итерации через свой файл данных с Bash и затем использовать awk для парсинга его. Что-то вроде этого должно помочь Вам начать (где so_ubuntu_20160706.txt Ваш файл сверху):

#!/bin/bash

FILENAME="/home/aploetz/scripts/so_ubuntu_20160706.txt"
VALUE_LIST=""
LAST_KEY=""
FIRST=1

while read -r LINE
do
  #KEY=$(echo $LINE | awk -F '/' '{print $1}')
  #VALUE=$(echo $LINE | awk -F '/' '{print $2}')
  #Use this line to set KEY and VALUE from awk on a single line
  eval $(echo $LINE | awk -F '/' '{KEY = $1; VALUE = $2} END {print "KEY=\""KEY"\";VALUE=\""VALUE"\""}')
  HEAD=$(echo $LINE | grep -v HEAD)

  if [[ "" != "$HEAD" ]]
  then
    if [[ $FIRST -eq 0 ]]
    then
      if [[ $KEY != $LASTKEY ]]
      then
        echo "$LASTKEY:$VALUE_LIST"
        VALUE_LIST=$VALUE
      else
        VALUE_LIST="$VALUE_LIST,$VALUE"
      fi
    else
      FIRST=0
      VALUE_LIST=$VALUE
    fi
  fi

  LASTKEY=$KEY
done < "$FILENAME"

#output last read key and values
echo "$KEY:$VALUE_LIST"

, Который производит этот вывод:

Core:Dev,master
FrontEnd:Dev,DoubleClick,master
Infrastructure:Dev,master
Software:Dev,Control,master

я делаю grep -v HEAD, и затем тест для пустой строки для захвата для записей, которые Вы не хотите.

1
ответ дан 1 December 2019 в 15:54

С awk

awk -F\/ '
  /HEAD/ {next} # skip lines matching HEAD
  $1 in a {
    a[$1] = a[$1]","$2; next
  }
  {
    if (last in a) print a[last]
    delete a
    a[$1] = $1":"$2
    last = $1
  }
  END {
    print a[last]
  }' input

, Если Вы не возражаете загружать целый файл в память И не заботитесь о порядке (или не возражают обращаться, после) простой путь с мог бы быть

awk -F\/ '
  /HEAD/ {next} # skip lines matching HEAD
  {
    a[$1] = a[$1] == "" ? $1":"$2 : a[$1]","$2
    next;   
  }
  END {
    for (i in a) print a[i]
  }' input | sort

или с современной версией GNU awk

gawk -F\/ '
  /HEAD/ {next} # skip lines matching HEAD
  {
    a[$1] = a[$1] == "" ? $1":"$2 : a[$1]","$2
    next;   
  }
  END {
    PROCINFO["sorted_in"] = "@ind_str_asc"
    for (i in a) print a[i]
  }' input
1
ответ дан 1 December 2019 в 15:54

Я предлагаю awk для этого случая. Создайте этот файл (имя: filter-au.awk):

#!/usr/bin/awk
BEGIN {
   # first field on output list. Ex: FrontEnd
   last_reg="xxxxxxxxxxxx";
   # second field on output list. Ex: Dev,DoubleClick,master
   parts="";
   # number of parts in second field. 
   # Ex: from previous case. num_parts_on_reg=3
   num_parts_on_reg=0;
   # flag to signalize a new part has to be included in
   # string parts
   flag_part=0;
}
{
    # not first line?
    if ( NR > 1 ) {
       # $1 field was changed? If yes, print register
       if ( $1 != last_reg ) {
          print last_reg ":" parts;
          num_parts_on_reg=0;
          parts="";
       }

       # fill string parts
       if ( num_parts_on_reg == 0  ) { 
            # first part
            parts=$2;
            num_parts_on_reg++;
       }
       else {
         # verify if $2 field has included in parts before
         split(parts, arr_values, ",", arr_seps)
         flag_part=0;
         for (p in arr_values) {
            if ( p == $2 ) {
               flag_part=1;
               break;
            }
         }
         # if not, include $2 in parts string
         if ( flag_part == 0 ) {
            parts=parts "," $2
            num_parts_on_reg++;
         }
       }
    } else {
       # first register
       parts=$2;
       num_parts_on_reg++;
    }
    last_reg=$1;
}
END {
   # print last register
   if (  num_parts_on_reg > 0 ) {
      print last_reg ":" parts;
   }
}

Затем выполните эти команды:

grep -v 'HEAD' input.txt | awk -F "/" -f filter-au.awk

input.txt является файлом с этим содержанием, которое Вы отправляете. Кажется работами:

Core:Dev,master
FrontEnd:Dev,DoubleClick,master
Infrastructure:Dev,master
Software:Dev,Control,master

Если FrontEnd/HEAD -> FrontEnd/master интерпретируется как две строки, создайте другой файл (имя: filter-au2.awk):

#!/usr/bin/awk
{
   if ( NF = 1 ) { print $0; }
   else {
      # split "->" lines in two
      print $1;
      print $2;
   }
}

и выполненный эти переданные по каналу команды:

cat input-awk.txt | awk -F "->" -f filter-au2.awk | awk -F "/" -f filter-au.awk

вывод:

Core:Dev,master
FrontEnd:Dev,DoubleClick,HEAD ,master
Infrastructure:Dev,master
Software:Dev,Control,master
2
ответ дан 1 December 2019 в 15:54

Другие вопросы по тегам:

Похожие вопросы: