Linux за българи: Форуми

Програмиране => Общ форум => Темата е започната от: bubu в Jul 02, 2009, 19:57



Титла: 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):
  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.  


Титла: 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):
  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


Титла: Re: AWK събиране на няколко реда в един
Публикувано от: VladSun в 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


Титла: Re: AWK събиране на няколко реда в един
Публикувано от: neter в 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


Титла: 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 ():
  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]


Титла: Re: AWK събиране на няколко реда в един
Публикувано от: VladSun в Jul 22, 2009, 23:46
Тази вечер се върнах на тази тема и ... единственото, което мога да кажа е:

radoulov++

 ;D ;D ;D


Титла: Re: AWK събиране на няколко реда в един
Публикувано от: KoIoSoS в 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