Posts tagged ‘piping’

Counting Lines in Multiple Files

2012-04-06 13:40

Looks like using Linux is really bound to slowly – but steadily – improve your commandline-fu. As evidence, today I wanted to share a little piece of shell acolyte’s magic that I managed to craft without very big trouble. It’s about counting lines in files – code lines in code files, to be specific.

For a single file, getting the number of text rows is very simple:

  1. $ wc -l some.file
  2.   142 some.file

Although the name wc comes from “word count”, the -l switch changes its mode of operation into counting rows. The flexibility of this little program doesn’t end here; for example, it can also accept piped input (as stdin):

  1. $ cat some.file | wc -l
  2. 142

as well as multiple files:

  1. $ wc -l some.file other.file
  2.   142 some.file
  3.    54 other.file
  4.   196 all

or even wildcards, such as wc -l *.file. With these we could rather easily count the number of lines of code in our project:

  1. $ wc -l **/*.py
  2.     3 foo/__init__.py
  3.   189 foo/main.py
  4.    89 foo/utils.py
  5.    24 setup.py
  6.   133 tests.py
  7.   438 all

Unfortunately, the exact interpretation of **/* wildcard seems to vary between shells. In zsh it works as shown above, but in bash I had it omit files from current directory. While it might make some sense here (as it would give a total without setup script and tests), I’m sure it won’t be the case all projects.

And so we need something smarter.

Triki z PowerShellem #9 – Potokowanie

2008-08-03 17:33

Jedną z głównych zalet powłok tekstowych w rodzaju PowerShella jest to, że pozwalają one na łączenie ze sobą małych, elementarnych poleceń w jedno duże zadanie. Gdy odbywa się to na zasadzie przekazywania wyników jednego programu na wejście następnego, mówimy o potokowaniu (pipelining). Znawcy basha mogliby rzucić np. takim przykładem:

  1. cat < program.cpp | grep int | wc --lines[/code]
  2. w którym to najpierw odczytywana jest zawartość pliku (<kbd>cat</kbd>), wyszukiwane są wszystkie linijki zawierające ciąg "int" (<kbd>grep</kbd>) i liczona jest ich ilość (<kbd>wc</kbd>). Całkiem oczywiste, prawda? ;-)
  3.  
  4. W PowerShellu przetwarzanie potokowe jest o tyle lepsze niż w innych powłokach, że między poleceniami wymienia się nie tekst, a obiekty .NET-owe. Dobrze byłoby więc wiedzieć, jak należy pisać własne skrypty, aby mogły one działać w potokach. Na szczęście nie jest to specjalnie trudne; prezentuje to ten oto skrypt:
  5. [csharp]# pokemonize.ps1
  6. # Zmienia litery w tekście na losowo duże lub małe
  7.  
  8. begin
  9. {
  10.     # Inicjujemy generator liczb losowych
  11.     $rand = New-Object Random
  12. }
  13.  
  14. process
  15. {
  16.     $str = $_.ToString()
  17.     $result = New-Object Text.StringBuilder
  18.    
  19.     # Zmieniamy znaki
  20.     for ($i = 0; $i -lt $str.Length; ++$i)
  21.     {
  22.         if ($rand.NextDouble() -lt [float]0.5)
  23.             { $newChar = [Char]::ToLower($str[$i]) }
  24.         else
  25.             { $newChar = [Char]::ToUpper($str[$i]) }
  26.            
  27.         $result.Append($newChar) | Out-Null
  28.     }
  29.    
  30.     # Wyświetlamy przetworzony ciąg
  31.     $result.ToString()
  32. }[/csharp]
  33. Tym, co on robi, jest losowa zmiana wielkości liter w ciągu stanowiącym tekstową reprezentację obiektu (lub obiektów), jaki dostaje na wejściu. Jednym słowem, dokonuje jego <em>pokemonizacji</em>... Pewnie dla niektórych byłoby to przydatne, ale powiedzmy, że to tylko taki przykład ;P
  34. Najważniejsze jest to, że podany skrypt działa dobrze na obiektach otrzymanych poprzez potok, czyli np. linijkach tekstu odczytanego z pliku poprzez <kbd>Get-Content</kbd>:
  35. [code]Get-Content ./Plik.txt | . ./pokemonize.ps1 | Out-Host

Dla każdego takiego obiektu (tutaj: wiersza z pliku) wykonywany jest blok process, w którym to ów obiekt jest reprezentowany jako zmienna $_. Można to sobie wyobrazić jako wnętrze pętli foreach, przelatującej po wszystkich obiektach z wejścia skrypt. Dodatkowo możemy jeszcze określić bloki: begin (uruchamiany na samym początku) i end (na końcu). W nich powinniśmy umieścić ewentualny kod inicjalizujący i/lub kończący pracę skryptu.

Tags: ,
Author: Xion, posted under Applications » Comments Off on Triki z PowerShellem #9 – Potokowanie
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.