Skrypty w awk-u.

0

Mam takie dwa zadanka; napisałam jakieś skrypty, ale nie do końca działają. :(
Zad.1
Plik zawiera listę studentów z wynikami ćwiczeń w formacie:

Imię_1 Nazwisko_1 Numer_1 wynik_1
Imię_2 Nazwisko_2 Numer_2 wynik_2
Imię_3 Nazwisko_3 Numer_3 wynik_3
...

Może występować wiele wyników dla każdego studenta, jednak dany student ma zawsze ten sam numer. Napisz skrypt w awk-u obliczający i wyświetlający na wyjściu dla każdego studenta: imię, nazwisko, numer, liczbę znalezionych wyników, wynik sumaryczny, wynik średni, oraz wynik średni obliczony z pominięciem najniższego i najwyższego.

No to napisałam coś takiego:

awk '
{   
  k = $1 OFS $2 OFS $3 # OFS
  c[k]++; d[k] = $NF
  suma[k]=suma[k]+$4
  maks[k]=(maks[k]>$4)?maks[k]:$4
  min[k]=(min[k]<$4)?min[k]:$4
  
}

END {  
   for (k in c)      
    print k, c[k], suma[k], suma[k]/c[k], (suma[k]-maks[k]-min[k])/(c[k]-2)
    } ' pliczek
 

Tak wygląda mój plik "pliczek":

 
Imie_1 Naz_1 Nr_1 8
Imie_2 Naz_2 Nr_2 1
Imie_3 Naz_3 Nr_3 9
Imie_1 Naz_1 Nr_1 6
Imie_2 Naz_2 Nr_2 3
Imie_1 Naz_1 Nr_1 4
Imie_3 Naz_3 Nr_3 5

__Wszystko by było fajnie, tylko minimum nie chce działać i nie mam pojęcia dlaczego. __

Zad.2

Plik zawiera listę studentów w formacie takim jak w zad.1

Napisz skrypt w awk-u sprawdzający, czy wszystkie wiersze zawierające ten sam numer w polu 3 mają dokładnie to samo imię i nazwisko w polach 1 i 2. Na wyjściu należy wyświetlić wszystkie wiersze z wejścia (bez zmian), oraz dodatkowy komunikat dla każdego wiersza, który zawiera numer, który wcześniej wystąpił z innym imieniem i/lub nazwiskiem.

Umiem tylko zliczyć takie same wiersze; nie mam pojęcia jak to polecenie ugryźć. Mam na razie coś takiego:

awk 'END {  
   for (k in c)      
    print k, c[k]
    } 
{   
  k = $1 OFS $2 OFS $3 # OFS  
  c[k]++; d[k] = $NF   
    }' pliczek

Proszę o jakieś wskazówki, bo ze skryptami się znamy od niedawna. :)

Pozdrawiam
Cherry_Lips

0

Przy pierwszym: co się stanie jak są tylko 2 wyniki? Przez co będziesz dzielił?

Poza tym lepiej się czyta jak się kod napisze w osobnym pliku i po ludzku sformatuje:

{
  name = $1 OFS $2 OFS $3
  count[name]++
  d[name] = $NF
  sum[name] = sum[name] + $4
  max[name] = (max[name] > $4) ? max[name] : $4
  min[name] = (min[name] < $4) ? min[name] : $4
}

END {
  for (name in count) {
    avg = sum[name] / count[name]
    avg_weighted = 0
    if (count[name] > 2) 
      avg_weighted = (sum[name] - max[name] - min[name]) / (count[name] - 2)
    print name, count[name], sum[name], avg, avg_weighted
  }
}

Co do drugiego, to można tak:

BEGIN {
  split("", users)
}

{
  print $0
  users[$3] = $1 OFS $2
  if (users[$3] != $1 OFS $2) {
    print "Duplicated user with id =", $3
  }
}
0

Zad.1
To minimum dalej nie działa.
Dla danych

Imie_1 Naz_1 Nr_1 10
Imie_1 Naz_1 Nr_1 8
Imie_1 Naz_1 Nr_1 9

Wypluwa średnią bez min i max równą 17, a nie 9.

I dzięki za trafne spostrzeżenie odnośnie tego, co się stanie jak będą tylko dwie oceny.

Zad.2
Wypisuje mi ostatni wiersz i nic nie liczy.

0

Przepraszam pomyłka. Nie chce mi się wstawiać Ci poprawionego kodu, bo to Cię nic nie nauczy. Mogę dać porady.

  1. Co wyjdzie z porównania "" oraz dowolnej liczby? Jaka jest domyślna wartość dla min[user]?
  2. Brakuje 1 warunku, znajdź gdzie.
0
  1. Nasza domyślna wartość min to string pusty, a string pusty zawsze jest mniejszy od jakieś liczby. Próbowałam na sam początek dopisać coś takiego:
!(name in count) {min[name]=$4}

ale nadal nie działa.

  1. Nie mam zielonego pojęcia.
0

Dobra, zadanie 1 już działa. Nieelegancko wygląda, ale trudno, jakoś przeżyję. Co do zadania 2 to nadal brak pomysłów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1