У меня есть этот текст:
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
?еще как?Спасибо.
Получил ответ! Благодарите всех в течение своего времени
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 "" }
'
Вы могли выполнить итерации через свой файл данных с 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
, и затем тест для пустой строки для захвата для записей, которые Вы не хотите.
С 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
Я предлагаю 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