Автор Тема: AWK събиране на няколко реда в един  (Прочетена 2744 пъти)

bubu

  • Напреднали
  • *****
  • Публикации: 113
    • Профил
Здравейте, имам нужда от малко помощ и ще съм много благодарен на всеки оказал съдействие :). Проблема е следния:

Имам един файл със съдържание, примерно:

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
и накрая да добавя запис колко ип адреса има тази програма. Имам едни идеи, но за сега все не успявам да достигна до точно решение. Ако някои може да помогне ще съм много признателен.
Активен

tyuio

  • Гост
Re: AWK събиране на няколко реда в един
« Отговор #1 -: Jul 02, 2009, 21:46 »
виж възможностите на perl, в сипан може някой да е правил такова нещо и то доста вероятно :)
Активен

lkr

  • Напреднали
  • *****
  • Публикации: 81
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #2 -: Jul 02, 2009, 21:59 »
Код
GeSHi (Ruby):
  1. #!/usr/bin/ruby
  2. raise "no file" unless ARGV[0]
  3. programs = {}
  4. File.open(ARGV[0]).each do |line|
  5.    line.strip!
  6.    name, ip = line.split
  7.    if !programs.has_key?(name)
  8.        programs[name] = { :ips => [ip], :count => 1 }
  9.    else
  10.        programs[name][:ips] << ip
  11.        programs[name][:count] += 1
  12.    end
  13. end
  14. programs.each { |k,v|
  15.    print k, " "
  16.    v[:ips].each { |x| print x, " " }
  17.    puts v[:count]
  18. }
  19.  

Ако нямаш руби...

Код
GeSHi (Perl):
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. die "No file" unless $ARGV[0];
  6. open my $fh, '<', $ARGV[0] or die "Cannot open $ARGV[0]";
  7. my (%progs,$name,$ip,$line);
  8. while(<$fh>) {
  9.    $line = $_;
  10.    chomp $line;
  11.    ($name,$ip) = split(" ",$line);
  12.    if (!exists($progs{$name})) {
  13.        $progs{$name} = { 'ips' => [$ip], "count" => 1 }
  14.    }
  15.    else {
  16.        push @{$progs{$name}->{'ips'}}, $ip;
  17.        $progs{$name}->{'count'}++;
  18.    }
  19. }
  20. close($fh);
  21.  
  22. foreach (sort keys %progs) {
  23.    print $_, " ";
  24.    map { print $_, " " } @{$progs{$_}->{'ips'}};
  25.    print $progs{$_}->{'count'}, "\n";
  26. }
  27.  

Код
GeSHi (Bash):
  1. laker@dg:~$ ./test.rb test
  2. 200 10.10.12.34 34.56.87.54 33.5.78.75 3
  3. 300 43.5.6.78 12.32.45.67 2
  4.  
« Последна редакция: Jul 02, 2009, 22:39 от lkr »
Активен

gizi_

  • Напреднали
  • *****
  • Публикации: 521
  • Distribution: Debian/Lenny, SLES/9-11
  • Window Manager: Gnome 2.22.3
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #3 -: 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% има по-добра алтернатива. Просто това ми дойде като бързо решение...
« Последна редакция: Jul 02, 2009, 22:24 от gizi_ »
Активен

VladSun

  • Напреднали
  • *****
  • Публикации: 2166
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #4 -: Jul 03, 2009, 00:10 »
Чист bash :)
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. if [ -f "$1" ]; then
  4. while read row; do
  5. row=(`echo "$row"`)
  6. if [ ${#data[${row[0]}]} = 0 ]; then
  7. data[${row[0]}]="${row[0]} ${data[${row[0]}]} ${row[1]}"
  8. else
  9. data[${row[0]}]="${data[${row[0]}]} ${row[1]}"
  10. fi
  11. done < $1
  12.  
  13. for row in "${data[@]}"; do
  14. count=`echo $row | grep -o " " | wc -l`
  15. echo $row $count
  16. done
  17. fi
« Последна редакция: Jul 03, 2009, 00:16 от VladSun »
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

VladSun

  • Напреднали
  • *****
  • Публикации: 2166
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #5 -: Jul 03, 2009, 00:21 »
2-ри вариант (без grep)
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. if [ -f "$1" ]; then
  4. while read row; do
  5. row=(`echo "$row"`)
  6. if [ ${#data[${row[0]}]} = 0 ]; then
  7. data[${row[0]}]="${row[0]} ${data[${row[0]}]} ${row[1]}"
  8. else
  9. data[${row[0]}]="${data[${row[0]}]} ${row[1]}"
  10. fi
  11. done < $1
  12.  
  13. for row in "${data[@]}"; do
  14. arow=(`echo $row`)
  15. count=`expr ${#arow[@]} - 1`
  16. echo $row $count
  17. done
  18. fi
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: AWK събиране на няколко реда в един
« Отговор #6 -: Jul 03, 2009, 01:59 »
Много сложни логики сте навързвали за случая
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. cat $1 | sort | while read i
  4. do
  5.    edno=${i% *}
  6.    if [ "$edno" = "$dve" ]; then
  7. echo -n " ${i#* }" >> $2
  8.    else
  9. echo -e -n "\n$i" >> $2
  10.    fi
  11.    dve=$edno
  12. done
  13.  
  14. grep . $2 | while read i
  15. do
  16.    echo "${i%% *}: $((`echo $i | wc -w`-1))"
  17. done
Или без "else"
Код
GeSHi (Bash):
  1. #!/bin/bash
  2.  
  3. cat $1 | sort | while read i
  4. do
  5.    edno=${i% *}
  6.    if [ "$edno" != "$dve" ]; then
  7. echo -e -n "\n$edno" >> $2
  8.    fi
  9.    echo -n " ${i#* }" >> $2
  10.    dve=$edno
  11. done
  12.  
  13. grep . $2 | while read i
  14. do
  15.    echo "${i%% *}: $((`echo $i | wc -w`-1))"
  16. done
Употреба
Код
GeSHi (Bash):
  1. ./script input.txt output.txt
« Последна редакция: Jul 03, 2009, 03:34 от neter »
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

bubu

  • Напреднали
  • *****
  • Публикации: 113
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #7 -: Jul 03, 2009, 02:39 »
Благодаря на всички. Проблемът е решен и всички са щастливи :). Наздраве  [_]3.
Активен

VladSun

  • Напреднали
  • *****
  • Публикации: 2166
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #8 -: Jul 03, 2009, 10:08 »
Много сложни логики сте навързвали за случая
Мойто гардже е по-хубаво :P
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

neter

  • Global Moderator
  • Напреднали
  • *****
  • Публикации: 3408
  • Distribution: Debian, SailfishOS, CentOS
  • Window Manager: LXDE, Lipstick
    • Профил
    • WWW
Re: AWK събиране на няколко реда в един
« Отговор #9 -: Jul 03, 2009, 10:50 »
Много сложни логики сте навързвали за случая
Мойто гардже е по-хубаво :P
[_]3
Активен

"Да си добре приспособен към болно общество не е признак за добро здраве" - Джиду Кришнамурти

radoulov

  • Напреднали
  • *****
  • Публикации: 116
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #10 -: Jul 03, 2009, 14:17 »
Код
GeSHi ():
  1. awk 'END {
  2.  for (k in r) print k, r[k], c[k]  
  3.  }
  4. {
  5.  r[$1] = r[$1] ? r[$1] FS $2 : $2
  6.  c[$1]++
  7.  }
  8. ' infile


Код
GeSHi (Perl):
  1. perl -lane'
  2.  push @{$r{$F[0]}}, $F[1];
  3.  print map "$_ @{$r{$_}} ".~~@{$r{$_}}."\n", keys %r
  4.    if eof
  5. ' infile


Zsh:

Код
GeSHi (Bash):
  1. unset a c
  2. typeset -A a c
  3.  
  4. while read -r p i; do
  5.  [ $a[$p] ] && a[$p]="$a[$p] $i" || a[$p]=$i
  6.  ((++c[$p]))
  7. done<infile
  8.  
  9. for k (${(k)a[@]}) print -r -- $k $a[$k] $c[$k]
« Последна редакция: Jul 03, 2009, 14:37 от radoulov »
Активен

VladSun

  • Напреднали
  • *****
  • Публикации: 2166
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #11 -: Jul 22, 2009, 23:46 »
Тази вечер се върнах на тази тема и ... единственото, което мога да кажа е:

radoulov++

 ;D ;D ;D
Активен

KISS Principle ( Keep-It-Short-and-Simple )
http://openfmi.net/projects/flattc/
Има 10 вида хора на този свят - разбиращи двоичния код и тези, които не го разбират :P

KoIoSoS

  • Напреднали
  • *****
  • Публикации: 107
  • Distribution: Slackware
  • Window Manager: Xfce4.8
    • Профил
Re: AWK събиране на няколко реда в един
« Отговор #12 -: Jul 23, 2009, 10:33 »
Код
GeSHi (Bash):
  1. #!/bin/sh
  2. KEY=$(cat $1 | cut -f1 -d" " | sort | uniq)
  3. for key in $KEY
  4. do
  5. BROI=$(grep -c ^$key $1)
  6. GRUP=$(grep ^$key $1 | cut -f2 -d" " | tr "\n" " ")
  7. printf "$key $GRUP$BROI\n" >> $2
  8. done
Активен

it is better to solve the right problem the wrong way than the wrong problem the right way   -- Doug McIlroy
Slackware Propaganda
http://video.google.com/videoplay?docid=-5210026640879077823