800px-Mucha-jobdziś znów gościnnie Kacper ze skryptem w służbie codzienności. pomysły zastosowania PS nie tylko do zadań administracyjnych, a również w zwykłych domowych warunkach, są mocno inspirujące. ponieważ wpisy dotyczą wyrażeń regularnych, sugeruję zapoznanie się z podstawami – np. na stronie regular-expressions.

dziś skrypt automatyzujący wyciąganie 'clippingów’ z kindle… oddaję głos Kacprowi:

.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.

Od kiedy posiadam Kindle’a kupiłem tylko jedną książkę w wersji papierowej. Wśród wielu zalet Kindle ukrywa się jedna, która w szczególności przypadła mi do gustu. Nazywa się ona – My Clippings.txt. Czytniki Amazonu przechowują w tym pliku wszystkie notatki czy zaznaczenia związane z czytanymi książkami. Przykładowe wpisy w tym pliku wyglądają tak:

Mastering System Center 2012 R2 Configuration Manager (Santos Martinez, Peter Daalmans and Brett Bennett)
- Highlight on Page 183 | Loc. 5477-87  | Added on Friday, January 09, 2015, 03:46 AM

Some of the information that is accessible with this extra level of logging is so useful that it is common practice to configure verbose and debug logging as a standard across the environment. There is additional overhead because more data is written to the logs, but it is minimal and should cause no impact to the operation of the system. Enabling verbose and debug logging requires two registry changes. First, you enable verbose logging by navigating to [HKEY_LOCAL_MACHINE\software\microsoft\ccm\logging@global] and changing the value LogLevel to 0 (which will require a permissions change on the @GLOBAL key). To enable debug logging, create a registry key called DebugLogging directly under [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CCM\Logging] Inside this registry key create a string value named Enabled and set its value to True.
==========
Mastering System Center 2012 R2 Configuration Manager (Santos Martinez, Peter Daalmans and Brett Bennett)
- Highlight on Page 184 | Loc. 5519-22  | Added on Friday, January 09, 2015, 03:47 AM

smsdbmon.log This log shows all activities such as inserts, updates, drops, and deletes from the Configuration Manager 2012 R2 database. smsprov.log This log shows the SQL transaction calls made from the Configuration Manager console or automation scripts via the SDK.
==========

Jak widać, mamy tu do czynienia z pewnym schematem, a to daje nam możliwość przekształcenia tych danych na inny format. Zazwyczaj kiedy czytam książkę pierwszy raz, robię dużo zaznaczeń, żeby potem mieć możliwość przypomnienia sobie tych kwestii, które mnie najbardziej interesowały. Można oczywiście przeglądać sobie zawartość My Clippings.txt w celu odświeżenia pamięci, jednak Kindle wpisuje tam wszystko w sposób chronologiczny. Jeśli więc czytam w tym samym czasie dwie książki, to i zaznaczenia będą się przeplatały. Aby ułatwić sobie życie postanowiłem napisać skrypt, który przetworzy dane z pliku My Clippings.txt tak, żeby można było np. filtrować z której książki zaznaczenia chcemy wyświetlić.:

[CmdletBinding()]
Param
(
    # Path to My Clippings.txt file
    [Parameter(Mandatory=$true,
                ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true,
                Position=0)]
    [Alias('FullName')]
    [String[]]$Path
)

Begin
{
    $Clippings = @()
}
Process
{
    Foreach($File in $Path){
        $Content = Get-Content -Path $File
        $i = 0

        do{
            $Clipping = ""
            # Prepare clipping
            do{
                $Clipping += $Content[$i]
                if($Clipping.EndsWith('AM') -or $Clipping.EndsWith('PM')){
                    $Clipping += ';'
                }
                $i++
                Write-Verbose -Message "i: $i"
            } while ($Content[$i] -ne '==========')

            $i++
            Write-Verbose -Message "Clipping content: $Clipping"

            # Format clipping
            # Extract clipping type
            $Pattern = "- (.*?) "
            $Match = $Clipping -match $Pattern
            $ClippingType = $Matches[1]
            
            # Extract book title
            $Pattern = ".*(?=- )"
            $Match = $Clipping -match $Pattern
            $BookTitle = $Matches[0]

            # Extract clipping content
            $Pattern = "\;(.*)"
            $Match = $Clipping -match $Pattern
            $ClippingContent = $Matches[1]

            # Prepare object
            $Props = @{
                BookTitle = $BookTitle
                ClippingType = $ClippingType
                Content = $ClippingContent
            }
            $Object = New-Object PSObject -Property $Props

            # Add object to array
            $Clippings += $Object

        } while ($i -ne ($Content.Length))
    }
}
End
{
    # Return clippings array
    return $Clippings
}

Jak widać skrypt nie jest skomplikowany, a najciekawsze fragmenty to regexy, które pobierają określony typ danych.

Na samym początku wstawiam średnik pomiędzy samą zawartość wpisu, a metadane. Prawdopodobnie nie jest to konieczne, ale znacznie mi ułatwiło tworzenie regexa w sekcji oznaczonej komentarzem „Extract clipping content”. Potem za pomocą wyrażenia „- (.*?) ” wydobywany jest typ wpisu. Zastosowanie nawiasów tworzy tzw. capturing groups, dzięki którym zwracana jest sama nazwa bez otaczających znaków. Jest to alternatywna wersja zapisu [Regex]::Matches($Clipping, $Pattern), który omawiałem w poprzednim wpisie.

Przy zapisywaniu tytułu książki do zmiennej wykorzystuję wyrażenie „.*(?=- )”. Ten regex zawiera tzw. positive lookahead, który zwraca wszystko od początku stringa aż do wystąpienia sekwencji znaków „- „, nie uwzględniając samej sekwencji (za to jest odpowiedzialny positive lookahead właśnie).

Na sam koniec, ponownie korzystając z capturing groups, pobieram wszystko co jest za znakiem średnika i zapisuję w zmiennej ClippingContent. Dalej jest już tylko stworzenie obiektu przy pomocy hashtable’a i dodanie go do tablicy Clippings, która jest zwracana przez skrypt.

Kacper

.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.

eN.

-o((:: sprEad the l0ve ::))o-

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Time limit is exhausted. Please reload CAPTCHA.