Титла: AWK събиране на няколко реда в един
Публикувано от: bubu в Jul 02, 2009, 19:57
Здравейте, имам нужда от малко помощ и ще съм много благодарен на всеки оказал съдействие :). Проблема е следния:
Имам един файл със съдържание, примерно:
200 10.10.12.34 300 43.5.6.78 200 34.56.87.54 200 33.5.78.75 300 12.32.45.67
Файла съдържа редове със запис в следния формат - номер на програма и после ип адрес, като номерата на програмата се повтарят. Това което искам да направя е да събера всички редове с един и същ номер на програма в един, примерно 200 10.10.12.34 34.56.87.54 33.5.78.75 3 и накрая да добавя запис колко ип адреса има тази програма. Имам едни идеи, но за сега все не успявам да достигна до точно решение. Ако някои може да помогне ще съм много признателен.
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: tyuio в Jul 02, 2009, 21:46
виж възможностите на perl, в сипан може някой да е правил такова нещо и то доста вероятно :)
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: lkr в Jul 02, 2009, 21:59
GeSHi (Ruby): #!/usr/bin/ruby raise "no file" unless ARGV[0] programs = {} File.open(ARGV[0]).each do |line| line.strip! name, ip = line.split if !programs.has_key?(name) programs[name] = { :ips => [ip], :count => 1 } else programs[name][:ips] << ip programs[name][:count] += 1 end end programs.each { |k,v| print k, " " v[:ips].each { |x| print x, " " } puts v[:count] }
Ако нямаш руби... GeSHi (Perl): #!/usr/bin/perl use strict; use warnings; die "No file" unless $ARGV[0 ]; open my $fh, '<', $ARGV[0 ] or die "Cannot open $ARGV[0]"; my (%progs,$name,$ip,$line); while(<$fh>) { $line = $_; ($name,$ip) = split(" ",$line); $progs{$name} = { 'ips' => [$ip], "count" => 1 } } else { push @{$progs{$name}->{'ips'}}, $ip; $progs{$name}->{'count'}++; } } map { print $_, " " } @{$progs{$_}->{'ips'}}; print $progs{$_}->{'count'}, "\n"; }
GeSHi (Bash): laker@dg:~$ ./test.rb test 200 10.10.12.34 34.56.87.54 33.5.78.75 3 300 43.5.6.78 12.32.45.67 2
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: gizi_ в Jul 02, 2009, 22:00
bubu объркал си ми се струва раздела във форума...по темата за на бързо: filepath=/path/to/file while read line; do prname=`echo $line | awk '{print $1}'`; ip=`echo $line | awk '{ print $2 }'`; if [ -e $filepath/$prname ]; then content=`awk 'NR == 1 { print }' $filepath/$prname`; echo "${ips}, $content" > $filepath/$prname; else echo "$ips" > $prname; fi done < $filepath/file
това би трябвало да ти потреди всички IP адреси във файлове...въпреки, че 100% има по-добра алтернатива. Просто това ми дойде като бързо решение...
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: VladSun в Jul 03, 2009, 00:10
Чист bash :) GeSHi (Bash): #!/bin/bash if [ -f "$1" ]; then while read row; do row=(`echo "$row"`) if [ ${#data[${row[0]}]} = 0 ]; then data[${row[0]}]="${row[0]} ${data[${row[0]}]} ${row[1]}" else data[${row[0]}]="${data[${row[0]}]} ${row[1]}" fi done < $1 for row in "${data[@]}"; do count=`echo $row | grep -o " " | wc -l` echo $row $count done fi
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: VladSun в Jul 03, 2009, 00:21
2-ри вариант (без grep) GeSHi (Bash): #!/bin/bash if [ -f "$1" ]; then while read row; do row=(`echo "$row"`) if [ ${#data[${row[0]}]} = 0 ]; then data[${row[0]}]="${row[0]} ${data[${row[0]}]} ${row[1]}" else data[${row[0]}]="${data[${row[0]}]} ${row[1]}" fi done < $1 for row in "${data[@]}"; do arow=(`echo $row`) count=`expr ${#arow[@]} - 1` echo $row $count done fi
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: neter в Jul 03, 2009, 01:59
Много сложни логики сте навързвали за случая GeSHi (Bash): #!/bin/bash cat $1 | sort | while read i do edno=${i% *} if [ "$edno" = "$dve" ]; then echo -n " ${i#* }" >> $2 else echo -e -n "\n$i" >> $2 fi dve=$edno done grep . $2 | while read i do echo "${i%% *}: $((`echo $i | wc -w`-1))" done
Или без "else" GeSHi (Bash): #!/bin/bash cat $1 | sort | while read i do edno=${i% *} if [ "$edno" != "$dve" ]; then echo -e -n "\n$edno" >> $2 fi echo -n " ${i#* }" >> $2 dve=$edno done grep . $2 | while read i do echo "${i%% *}: $((`echo $i | wc -w`-1))" done
Употреба GeSHi (Bash): ./script input.txt output.txt
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: bubu в Jul 03, 2009, 02:39
Благодаря на всички. Проблемът е решен и всички са щастливи :). Наздраве [_]3.
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: VladSun в Jul 03, 2009, 10:08
Много сложни логики сте навързвали за случая Мойто гардже е по-хубаво :P
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: neter в Jul 03, 2009, 10:50
Много сложни логики сте навързвали за случая Мойто гардже е по-хубаво :P
[_]3
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: radoulov в Jul 03, 2009, 14:17
GeSHi (): awk 'END { for (k in r) print k, r[k], c[k] } { r[$1] = r[$1] ? r[$1] FS $2 : $2 c[$1]++ } ' infile
GeSHi (Perl): perl -lane' push @{$r{$F[0]}}, $F[1]; print map "$_ @{$r{$_}} ".~~@{$r{$_}}."\n", keys %r if eof ' infile
Zsh: GeSHi (Bash): unset a c typeset -A a c while read -r p i; do [ $a[$p] ] && a[$p]="$a[$p] $i" || a[$p]=$i ((++c[$p])) done<infile for k (${(k)a[@]}) print -r -- $k $a[$k] $c[$k]
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: VladSun в Jul 22, 2009, 23:46
Тази вечер се върнах на тази тема и ... единственото, което мога да кажа е:
radoulov++
;D ;D ;D
Титла: Re: AWK събиране на няколко реда в един
Публикувано от: KoIoSoS в Jul 23, 2009, 10:33
GeSHi (Bash): #!/bin/sh KEY=$(cat $1 | cut -f1 -d" " | sort | uniq) for key in $KEY do BROI=$(grep -c ^$key $1) GRUP=$(grep ^$key $1 | cut -f2 -d" " | tr "\n" " ") printf "$key $GRUP$BROI\n" >> $2 done
|