Nowe posty

xx Dystrybucja pod HP Omen (6)
Wczoraj o 23:30:08
xx [Poradnik] Wyszukiwanie Sterowników (2)
Wczoraj o 21:08:23
lamp Problem z Linux Lite po instalacji (0)
Wczoraj o 19:50:30
xx Ile pingwinów? (1)
Wczoraj o 08:59:24
xx konfiguracja pale moon (0)
2024-03-24, 21:53:42
xx Plasma 6 w Neonie ssie trochę mniej ... (10)
2024-03-23, 02:38:11
xx problem z instalacja sterowników do karty sieciowej (3)
2024-03-18, 18:10:16
xx Plik abc.001 (1)
2024-03-17, 17:48:27
xx Zlecę dopracowanie programu w MatLab (0)
2024-03-13, 15:28:40
xx Linux Mint 21.3 XFCE brak dźwieku po paru minutach (karta muzyczna zintegrowana) (5)
2024-03-12, 23:07:01

Autor Wątek: Pomoc poczatkującej  (Przeczytany 2676 razy)

Daisy19

  • Gość
Pomoc poczatkującej
« dnia: 2014-09-25, 17:50:15 »
Hej, jestem totalnie zielona z Linuksa dopiero się uczę wiec i pytanie będzie banalne.

Otóż w jednym pliku mam przykładowo 2 wierszyki dla dzieci , chce obliczyć ilość wyrazów tylko jednego z nich.

Umiem to zrobić używając wc -w i head i tail  ,ale liczę ręcznie ile ilość linii wiersza by odpowiednio dopasować polecenie. Wiem jednak ze przy plikach z masą linii nie jest to dobre rozwiązanie .
Czy jest jakiś inny sposób albo polecenie ???

Pozdrawiam

alvaro

  • Gość
Pomoc poczatkującej
« Odpowiedź #1 dnia: 2014-09-25, 18:01:50 »
Cytat: Daisy19
Hej, jestem totalnie zielona z Linuksa dopiero się uczę wiec i pytanie będzie banalne.

Otóż w jednym pliku mam przykładowo 2 wierszyki dla dzieci , chce obliczyć ilość wyrazów tylko jednego z nich.

Umiem to zrobić używając wc -w i head i tail  ,ale liczę ręcznie ile ilość linii wiersza by odpowiednio dopasować polecenie. Wiem jednak ze przy plikach z masą linii nie jest to dobre rozwiązanie .
Czy jest jakiś inny sposób albo polecenie ???

Pozdrawiam
A w jaki sposób są oddzielone od siebie te "wierszyki"? Zawsze są tylko dwa czy ich liczba może być zmienna? Możesz podać jakiś przykład?

Offline ultr

  • Users
  • Guru
  • *****
  • Wiadomości: 1177
    • Zobacz profil
Pomoc poczatkującej
« Odpowiedź #2 dnia: 2014-09-25, 19:27:29 »
Jeśli wierszyki oddzielone są pustymi liniami, a same ich nie zawierają, to można tak:

1. wczytywać plik linia po linii
2. sprawdzać czy linia nie jest pusta
3. jeśli nie, to incrementować licznik
4. jeśli pusta, to wypisać wartość licznika* i zresetować licznik
5. zapętlić
*) o ile nie jest równy 0, co oznacza, że wierszyki rozdziela większa ilość pustych linii

Spoiler:
#!/bin/bash -e
licznik=0
function pisz {
  [ "$licznik" -gt 0 ] && echo "Ilosc slow w wierszyku: $licznik"
  return 0
}
while read -r linia; do
  if [ -n "$linia" ]; then
    wyrazy=$(wc -w <<< "$linia")
    ((licznik += $wyrazy))
  else
    pisz
    licznik=0
  fi
done < wierszyki.txt
pisz
Jeśli w wierszykach są np. pojedyncze odstępy, a same wierszyki rozdzielone są ich większą ilością, to można łatwo przerobić skrypt dodając drugi licznik do zliczania wielkości przerwy.

Cytat: "Daisy19"
Hej, jestem totalnie zielona z Linuksa dopiero się uczę
Powodzenia!

alvaro

  • Gość
Pomoc poczatkującej
« Odpowiedź #3 dnia: 2014-09-26, 17:12:14 »
Zakładając, że wiersze miałyby być oddzielone pustymi liniami to skrypt mógłby wyglądać tak:
#!/usr/bin/env bash

c() {
  awk 'BEGIN {l=0; w=0} m=/^[[:blank:]]*$/ {if (l) print w; l=0; w=0} !m {l++; w+=NF} END {if (l) print w}' "${1:-/dev/stdin}" 2>/dev/null
}

if [[ "$#" -gt 0 ]]; then
  for arg; do
    [[ -r "$arg" ]] || continue
    c "$arg"
  done
else
  c
fi
Chyba nie muszę szczegółowo tłumaczyć głównej konstrukcji. Jeśli podane są jakieś argumenty to skrypt traktuje je jako nazwy plików do sprawdzenia a w przeciwnym wypadku czyta dane ze standardowego wejścia.
Pokrótce omówię zagnieżdżony skrypt AWK.

BEGIN {l=0; w=0}
Przed przetwarzaniem kolejnych linii dokonujemy inicjalizacji licznika linii (l) oraz licznika słów (w).

m=/^[[:blank:]]*$/ {if (l) print w; l=0; w=0} !m {l++; w+=NF}
Jeśli aktualnie analizowana linia jest pusta (podany wzorzec uwzględnia linie zawierające co najwyżej same białe znaki) to wypisujemy stan licznika w jeśli licznik l on różny od zera. Musimy także pamiętać o ich wyzerowaniu.
W przeciwnym wypadku (gdy linia nie pasuje do wzorca m, czyli zawiera tekst) inkrementujemy licznik l oraz zwiększamy licznik w o liczbę słów w linii (NF oznacza liczbę pól).

END {if (l) print w}
Na koniec (po przejrzeniu wszystkich linii) wypisujemy wartość licznika w jeśli wartość licznika l jest niezerowa. Jest to potrzebne ze względu na to, że dane mogą kończyć się niepustą linią a bez tego ostatni "wierszyk" nie zostałby uwzględniony.