Friday, August 9, 2019

Doppelte Zeilen aus unsortierten Dateien entfernen

Das Kommando uniq(1) aus den Coreutils entfernt wiederholt auftretende Zeilen aus sortierten Dateien. D.h. die Zeilen müssen vorher z.B. mit sort(1) sortiert werden und die Daten verlieren durch die Sortierung die Reihenfolge. Soll die Reihenfolge aber erhalten bleiben, findet sich für das Problem keine Lösung in den Coreutils.

Die Lösung: Folgendes AWK entfernt wiederholt auftretende Zeilen in einer unsortierten Datei, so das in der Ausgabe keine Zeile doppelt vorhanden ist, wobei aber die ursprüngliche Reihenfolge der Zeilen erhalten bleibt, denn es ist keine Voraussetzung, dass die Eingabe sortiert sein muss:

awk '!a[$0]++' path/to/file

Nur bestimmte Spalten berücksichtigen

Sollen nur bestimmte Spalten berücksichtigt werden, gibt man die Position der Spalten entsprechend an: Für die erste Spalte awk '!a[$1]++' path/to/file, für die zweite Spalte awk '!a[$2]++' path/to/file usw. usf. Es können auch mehrere Spalten angegeben werden: Hier ein Beispiel für die zweite, dritte und fünfte Spalte: awk '!a[$2$3$5]++' path/to/file.

PS: Der Spaltentrenner kann mit dem AWK Schalter -F angegeben werden.

Doppelte Zeilen aus sortierten Dateien entfernen

Der Vollständigkeit halber noch die gängige Lösung, um doppelte Zeilen aus sortierten Dateien zu entfernen.

sort -u path/to/file

Oder wenn doch Eingenschaften aus uniq(1) benötigt werden:

sort path/to/file | uniq

Sunday, November 4, 2018

LibreOffice: Inhalts- und Stichwortverzeichnis automatisch aktualisieren

Die Verzeichnisse wie Inhalts- oder Stichwortverzeichnis in einem LibreOffice Writer Dokument, können beim Speichern oder Exportieren automatisch aktualisiert werden. Dazu verknüpft man folgendes Makro an die Ereignisse Dokument speichern und Dokumentkopie speichern oder exportieren.

Den Dialog dazu findet man unter Extras/Makros/Bearbeiten und für das Zuweisen unter Extras/Makros/Verwalten/LibreOffice Basic/Zuweisen.

loMakroDocumentIndexesUpdate1.png

loMakroDocumentIndexesUpdate2.png

Das Makro

REM  *****  BASIC  *****

Sub Main

End Sub	

REM Verzeichnisse aktualisieren
REM Siehe auch: https://www.oooforum.de/viewtopic.php?f=18&t=70890
REM             https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=2557
Sub DocumentUpdateIndexes
	On Error Goto ErrorHandler ' Enables error handling

	oIndexes = ThisComponent.getDocumentIndexes()
	for i = 0 to oIndexes.getCount () - 1
		oIndexes (i).update
	next

	' Label
	ErrorHandler:
End Sub

Sub DokumentSpeichern
	DocumentUpdateIndexes
End Sub

Sub DokumentkopieSpeichernOderExportieren
	DocumentUpdateIndexes
End Sub

Friday, August 4, 2017

Perl: Zufälligen Schlüssel/Key eines Hash

Auf einen zufälligen Schlüssel eines Hash, kann man mit der Funktion keys zugreifen. Die Funktion keys, gibt alle Schlüssel eines Hash, als Liste zurück, von der dann ein Wert zufällig abgefragt werden kann:

#!/usr/bin/perl

my %alphabet = (
    A => 1,
    B => 2,
    C => 3,
    D => 4,
    E => 5,
    F => 6,
    G => 7,
    H => 8,
    I => 9,
    J => 10,
    K => 11,
    L => 12,
    M => 13,
    N => 14,
    O => 15,
    P => 16,
    Q => 17,
    R => 18,
    S => 19,
    T => 20,
    U => 21,
    V => 22,
    W => 23,
    X => 24,
    Y => 25,
    Z => 26,
);

my @keys = keys %alphabet;

# zufälliger Key

my $buchstabe = $keys[ rand @keys ];
my $position  = $alphabet{$buchstabe};

printf "Der Buchstabe %s, ist der %i. im Alphabet.\n", $buchstabe, $position;

Es ist auch möglich, direkt auf einen zufälligen Wert eines Hash zuzugreifen. Das funktioniert, analog mit der Funktion values:

my @values = values %alphabet;
print $values[ rand @values ] . "\n";

PS: In den Kommentaren, hat Christian eine etwas schnellere Möglichkeit aufgezeigt:

my @list = %alphabet;
my $random_key = $list[(1|rand@list) -1];
my $random_val = $list[1|rand@list];

Das bitweise ODER mit 1 sorgt dafür, dass das letzte Bit des Ergebnisses von rand auf 1 gesetzt wird. Dadurch entsteht immer eine ungerade Zahl (1|0 => 1, 1|1 => 1, 1|2 => 3, 1|3 => 3, …). Es wird also nur auf ungerade Indizes des Arrays zugegriffen, wo in diesem Fall die Values abgelegt sind. Da dabei immer eine Zahl größer 0 generiert wird, kann mit einem einfachen -1 immer auf die geraden Indizes mit den Keys zugegriffen werden.

Thursday, June 8, 2017

Perl: Dateien von I2P Eepsites und/oder Tor hidden services downloaden

Ich programmiere einen Feedreader.

Dieser hat nun auch das Proxy Attribut des Perl Moduls LWP::UserAgent implementiert, um z.B. Feeds von I2P Eepsites und/oder Tor hidden services abonnieren zu können.

Wie man mittels der Perl Module URI::Fetch und LWP::UserAgent, eine solche URL downloadet, will ich hier kurz skizzieren:

#!/usr/bin/env perl

use URI;
use URI::Fetch;

use LWP::UserAgent;
use LWP::Protocol::socks;

my $uri = URI->new("http://example.i2p/");

my $ua = LWP::UserAgent->new();
$ua->proxy( "http", "http://localhost:4444" );

my $response = URI::Fetch->fetch( $uri, UserAgent => $ua )
  || die URI::Fetch->errstr;

print $response->content;

Eepsite: Die (Pseudo-)Top-Level-Domain .i2p

Es wird mittels $ua->proxy( "http", "http://localhost:4444" ); der zu verwendende HTTP-Proxy gesetzt. Analog funktioniert das so auch mit anderen Protokollen, wie z.B. HTTPS, FTP usw.

Siehe auch: http://search.cpan.org/perldoc/LWP::UserAgent.

Tor hidden services: Die (Pseudo-)Top-Level-Domain .onion

Für das SOCKS-Protokoll, muss zusätzlich das Modul LWP::Protocol::socks eingebunden werden.

Um bspw. eine Datei von einem Tor hidden service downzuloaden, muss $ua->proxy( "http", "socks://localhost:9050" ); gesetzt werden.

Siehe auch: http://search.cpan.org/perldoc/LWP::Protocol::socks.

Thursday, October 20, 2016

Kommentar: Software lokal installieren mit dem Linux Installations-Dreisatz

Wird ein Programm nicht über die Paketverwaltung angeboten, bleibt nur das Programm selbst zu installieren.
Hierfür wird i.d.R. der Linux Installations-Dreisatz aufgezeigt, der sich aus den GNU build utils der GNU Toolchain ergibt, um Software zu installieren. Auch selbst entwickelte Programme installiert man i.d.R. auf diese Weise.

Der Linux Installations-Dreisatz im Detail

Als Installations-Dreisatz bezeichnet man das Kompilieren und Installieren eines Programms mit folgenden drei Befehlen:

./configure --prefix=/usr/local
make
make install

In der Standardeinstellung ist normalerweise schon die Installation nach /usr/local vorgesehen. Denn /usr/bin gehört dem System und ist tabu. Siehe GNU Autoconf Handbuch Abs. 4.13 Default Prefix.

Die drei Schritte sollten bekannt sein.

Nun ist aber in vielen Foren und Anleitungen zu lesen, dass für das make install Superuser-Rechte benötigt werden. Doch das ist falsch. Der richtig Ansatz führt über die Gruppe staff, denn diese Gruppe ist vorgesehen um Software, ohne Superuser-Rechte lokal zu installieren. Siehe wiki.debian.org/SystemGroups.

Fügt man sein Benutzerkonto der Gruppe staff hinzu, erhält man Schreibrechte unterhalb /usr/local und /var/local, so dass zur Installation kein erweiterten Rechte notwendig sind (was auch einen Sicherheitsgewinn bringt). Die Berechtigungen können im Detail wie folgt ermittelt werden: find / -group staff -writable 2>/dev/null.

Hat man Software lokal installiert, muss die Umgebungsvariable PATH entsprechend angepasst werden und /usr/local/bin und /usr/local/sbin hinzugefügt werden (ggf. auch in der Crontab). Und mittels ldconfig /usr/local/lib, der dynamische Linker angewiesen werden, auch nach Libs unter /usr/local/lib zu suchen.

Mehr Details zum Installations-Dreisatz findet man in der einschlägigen Literatur.

Als Alternative zur lokalen Installation, sollte aber immer das Erstellen eines distributions-spezifischen Pakets in Betracht kommen. Denn oft bieten Software-Projekte kein make uninstall an, oder es wurde nur unzureichend implementiert.