blog · git · desktop · images · contact & privacy · gopher


„vipe“ in kurz und „pick“

In den moreutils gibt es das schöne Tool "vipe": Damit kann man interaktiv in einer Pipe die Daten editieren.

$ ls -al | vipe | whatever

Das originale "vipe" ist ein Perl-Skript und hat etwa 25 funktionale Zeilen. Um die 20 davon kann man sich sparen, wenn man es in einem Shellskript realisiert:

#!/bin/bash

# vipe: Use your $EDITOR to edit text in pipelines.

tmp=$(mktemp)
trap 'rm -f "$tmp"' 0

cat >"$tmp"
${EDITOR:-vim} "$tmp" </dev/tty >/dev/tty
cat "$tmp"

Gut, okay, er beachtet kein "$VISUAL" und auch kein "/usr/bin/editor" (d'uh). Die Zeit, in der zwischen "$EDITOR" und "$VISUAL" unterschieden wurde, erkläre ich aber hiermit einfach mal für beendet.

Was kann man damit nun realistischerweise Interessantes tun? In dem schönen Buch The UNIX Programming Environment, was ich alleine deshalb cool finde, weil es so alt ist und damals noch mit troff gesetzt wurde, wird als ein Beispielprogramm "pick" eingeführt. "pick" ist dazu gedacht, den Nutzer interaktiv aus einer Reihe von Einträgen auswählen zu lassen. Im Buch ist das ein C-Programm und funktioniert durch sequentielles Abfragen: "Nutzer, möchtest du diesen Eintrag auswählen? [J/n]" Dann geht es weiter zum nächsten Eintrag. Es gibt kein "Undo", man kann nicht mehrere Dinge auf einmal auswählen und so weiter.

Einen etwas anderen Ansatz aber dasselbe Ziel verfolgt dieses kleine Skript, das auf "vipe" aufsetzt:

#!/bin/bash

# pick: Use your $EDITOR to pick items from a list.

{
    [[ "$@" == "-" ]] && cat || { IFS=$'\n'; echo "$*"; }
} | sed 's/^/  /' | vipe | sed -rn 's/^[^ ] (.*)/\1/p'

Einsatzbeispiele:

Das Grundprinzip ist:

Dadurch, dass man im Editor seiner Wahl landet, kann man die Selektion ziemlich effektiv vornehmen. In Vim gibt es zum Beispiel die Möglichkeit, vertikal zu selektieren, andere Editoren können ähnliches. Man wechsle also beispielsweise mit "Strg-V" in den Modus "visual block", markiere dann eine Reihe von Zeilenanfängen und drücke dann "rr". Damit gelten all diese Zeilen als markiert, weil sie nun mit einem "r" statt einem Leerzeichen beginnen. Dann mit "ZZ" speichern und beenden und die Auswahl ist getätigt.

Screenshot

Und man kann natürlich auch nach komplexeren Mustern selektieren -- das ginge zwar auch komplett ohne "pick" mit einem einfachen "grep", aber manchmal ist man sich ja nicht ganz so sicher, wie das Muster konkret aussehen muss, und da ist es dann schon besser, wenn man das via "WYSIWYG" machen kann.

Das zweite Einsatzbeispiel oben sollte auch erklären, weshalb "-" notwendig ist, um von stdin zu lesen. Würde man sagen, "ohne Argumente liest du von stdin, ansonsten nimmst du die Argumente", dann hätte man ein Problem, falls hier "grep" kein Ergebnis liefert: "pick" würde dann nämlich von stdin zu lesen versuchen. Das ist für den Nutzer aber nicht ersichtlich -- das Programm würde "stehenbleiben". Diese Problematik wurde auch im Buch schon aufgeworfen.

PS.: An einigen Stellen wurde in diesem Posting keine Rücksicht auf Dateinamen mit Leerzeichen genommen, geschweige denn solche mit anderem Ungeziefer wie Newlines.