Textoperationen für Systemadministratoren (Linux Shell Tools, Texteditoren, Microsoft Excel)

(Last Updated On: 12. April 2016)

Als Systemadministrator haben Sie es oft mit TExtdaten zu tun, die Sie auf irgendeine Art und Weise verarbeiten oder sortieren müssen. Dabei kämpfen Sie an allen Fronten: in der Windows- oder Linux-Kommandozeile, mit Microsoft Excel und mit simplen Texteditoren – seien es Linux/Unix-Shelleditroen wie vi, vim oder nano oder grafische Windows-Editoren wie Notepad, Wordpad oder Notepad++. Und zu guter letzt vergleichen Sie noch unterschiedliche Versionen einer Textdatei auf Unterschiede und fügen diese Unterschiede zusammen.

In diesem Blogpost zeige ich Ihnen anhand einiger Situationen aus meinem Administrationsalltag, wie Sie verschiedene Herausforderungen mit Hilfe von Kommandozeilen- und Shell-Kommandos, Microsoft Excel und den TExteditoren vi (Linux) und Notepad++ (Windows) lösen können. Der Post wird aktualisiert, sobald mir irgendwann wieder eine neue Situation begegnet, an der ich feilen muss.

Die Linux-Textverarbeitungstools auf Shell-Ebene

Den output von kommandos in Skripten loggen

Wenn ihr unter Linux ein Skript, etwa in Form einer .sh-Datei, schreibt, ist es euch vielleicht schonmla passiert, dass euer Skript nicht durch gelaufen, also auf einen Fehler gestoßen, ist. Zur Fehlersuche machen sich viele die Mühe und führen die einzelnen kommandos einen nach dem anderen aus, was jedoch absolut unnötig ist.

Stattdessen könnt ihr das Skript ausführen mit

sh -x <Skriptdatei>
bzw. 
bash -x <Skriptdatei>

und euch wird der Output eurer kommandos angezeigt.

Und ihr könnt sogar, ohne das Skript live bie der Ausführung zu beobachten, den Output der Kommandos loggen. Dabei empfiehlt es sich, normalen Output in eine Datei, und Fehlermeldungen in eine sepzielle andere Datei zu loggen. Dazu würde ich einfach an das kommadno anhängen

sh -x <SkriptDatei> > normal.log 2> error.log

somit wird der normale Output der Skript-Kommandos in die Datei normal.log geschrieben und alle Fehlermeldungen in die Datei error.log. Wenn ihr nun eure Skriptdatei beispielsweise über die /etc/crontab so einplant, könnt ihr euch am nächsten Tag, wenn euer skript nicht sauber durchgelaufen ist, ansehen, warum das passiert ist. Dabei muss euch bewusst sein, dass die einfahcen >-Zeichen dafür sorgen, dass die Datei jedesmal überschrieben wird, wenn die Log-Datei neu befüllt wird, das heißt die alten Einträge verschwinden dann. WEnn ihr stattdessen die Einträge jedesmal an den aktuellen Inhalt einfach nur dranhängen wollt (ohne den alten zu überschrieben), müsst ihr statt einem > zwei hintereinander schreiben, also

sh -x <SkriptDatei> >> normal.log 2>> error.log

Was meine persönlich preferierte einstellung ist, mit dem Kommando date füge ich dann jedesmal, wenn das Skript läuft, einen aktuellen Zietstempel hinzu, damit ich später unterscheiden kann, welcher Log-Abschnitt zu welchem TAg gehört.

Wenn du mit Absicht verhindern möchtest, dass du versehentlich DAteien überschreibst, indem du in deinen Skripten statt zwei > nur einen > schreibst, dann kannst ud dies verhindern, indem du in der Shell den Befehl

set -o noclobber

wirfst. Von nun an kannst du Dateien nicht mehr mit einem > überschreiben, es sei denn du schreibst ab sofort >| oder stellst den Parameter wieder um über

set +o noclobber

Ich persönlich setze diesen Parameter immer wenn ich Skripte schreibe oder manuell mit Dateien auf der Kommandozeile rumspiele, zur Sicherheit.

Daten suchen und extrahieren

Daten extrahieren und formatieren mit awk

mit awk können wir die Ausgabe von anderen Kommandos formatieren. Nehemn wir als Beispiel mal die Datie /etc/passwd, deren inhalt aus Zeilen im Folgenden Format besteht
sshd:x:497:495:SSH daemon:/var/lib/sshd:/bin/false

Was ist nun, wenn wir nicht die gesamte /etc/passwd asugeben wollen, sondern nur die Benuzternamen aller Benutzer sehen wollen?

Für diesen Fall können wir awk benutzen, um die einzelnen Felder, die durch Doppelpunkte (:) voneiannder getrennt werden, in Variablen speichern. Die Variable $1 steht für das erste Feld (den Benutzernamen), $3 für das drittte Feld (die uid). Wenn wir also nur die Namen aus der Datei, sprich das erste Feld, ausgeben wollen, setzenw ir das Kommando ab:

awk -F":" ' { print $1 }  ' /etc/passwd

und wir bekommen nun nur noch die Usernamen angezeigt.

Zusätzlich ist jetzt noch möglich, nicht nur die Spalte, sondern aucheinen Zeilenbereich auszuwäheln, den man sich anzeigen lassen möchte. Dazu würden wir unser Kommando einfach abändern in.

awk -F":" ' NR==5,NR==10{ print $1 }  ' /etc/passwd

Damit bekomemn wir nur die Zeilen 5 bis 10.

Wenn wir jetzt mehrere Spalten haben wollen, z. B. zusätzlich noch die uid, ändern wir das kommando ab in.

awk -F":" ' NR==5,NR==10{ print $1,$3 }  ' /etc/passwd

WAs euch jetzt noch auffallen wird ist, dass die Spalten unschön formatiert sind, da die Spalten nicht immer sauber untereinander stehen, je nachdem wie lange die Vorgängerspalte ist.

Wir können aber unsere Spalten so anordnen, dass zusammengehörige Zellen in der selben Spalte sich immer die selbe Menge an Zeichen reservieren, und erst nach diesem Reservierungsraum die nächste Spalte beginnen kann. So stehen die Sptlen sauber untereinander. Das können wir tun mit

awk -F":" ' NR==5,NR==10{ printf "%-8s %3d\n" $1,$3 }  ' /etc/passwd

Wie ist das nun zu interpretieren? Als erstes gilt es zu erkenenn, dass wir nurn printf statt print verwendne. %- heißt, dass wir die erste Spalte linksbündig positionieren und nur % heißt, dass wir die dritte Spalte rechtsbündig positionieren. Die Zahlen danach stehen für die Anzahl der zu reservierenden Ziechen für die Spalte und die kleinen Buchstbaen am Schluss sind der Datentyp – s für „string“, also Zeichenkette, und d für „decimal“, als Dezimalzahl. Das \n ganz am Ende sagt aus, dass wir danach eine neue Zeile anfangen wollen.

Jetzt wollen wir noch Überschriften für unsere Spalten haben. Dazu ändern wir unseren Befehl ab in.

awk -F":" '
 BEGIN ( printf "%-8s %-3s\n", "User", "UID" )
 NR==5,NR==10{ printf "%-8s %3d\n" $1,$3 }  ' /etc/passwd

Na, seid ihr dahintergestiegen? an den Anfang der Datei wird wieder die erste Spalte linksbündig mit acht Zeichen Reservierung mit der Beshriebung „user“ und die rechte Spalte, diesmal allerdings ebenfalls linksbündig psotioniert, mit 3 Zeichen Reseriverung und der Beschreibung „UID“ gesetzt.

Spalten, die nur Zahlenwerte enthatlen, könnenw ir zusammenrechnen

 cat test.csv | awk -F, '{total+=$3} END {print "Summe: "total}'

Jetzt wollen wir nur Datensätze ausgeben, bei denen die letzte Zeile einen kleinbcuhstaben enthält.

cat test.csv | awk -F, '{if ($NF ~ "[a-z]") print}'

 

Daten extrahieren mit cut

die Werte aus den einzelnen Spalten in der /etc/passwd könnten wir aber auch mit cut extrahieren. Beispielsweise können wir, wenn wir nur den usernamen (1. Spalte) wollen, sagen

cat /etc/passwd | cut  -d":" -f1

Wir nehmen also den Output von cat /etc/passwd, sagen cut, dass der Trenner zwischen den Spalten ein Dopplepunkt ist, und geben mit -f1 an, dass wir nur die erste Spalte wollen. Wenn wir jetzt noch die UID dazu wollen, geben wir an

cat /etc/passwd | cut -d":" -f1,3

zählen mit wc

manchmal möchte ich wissen, ob  sich die Anzahl an DAteien in einem Ordner geändert haben. Die Anzahl an Dateien, die das komamdno ls -la in einem Ordner findet, lasse ich mir ausgeben mit

ls -la | wc -l

denn wc -l zählt die Anzahl der Zeilen einer Ausgabe. Wenn ich hingegen beispielsweise nur die Anzahl der Unterordner haben möchte, arbeite ich mit find

find . -type d | wc -l

Wenn ihr ein Kommando nur an wc piped, also beispielswiese

cat /etc/passwd | wc

dann stehen in der ersten Spalte die Anzahl der Zeilen, in der zweiten die Anzahl der erkannten Worte (also zusammengeschriebene Buchstbaen, die durch ein LEerezichen, TAbstopp, Punkt, Doppelpunkt, Komma oder Ähnliches getrennt werden) und ganz zum Schluss die Gesamtanzahl an Zeichen in der Ausgabe.

schauen, welche Dateien einen bestimmten TExt enthalten mit grep

Manchmal wisst ihr, dass eine bestimmte Textdatei einen gewissen Text enthalten muss, seid euch aber nicht mehr sicher, welche. Oder ihr möchtet sicher gehen, dass ein bestimmter Konfigurationsparameter, den ihr geändert habt, nicht noch einmal in einer anderen Konfiugrationsdatei gesetzt wird, sodass eure Änderung wieder überschrieben wird.

Mit dem kommando

grep 'max_memory' /etc/*

sucht ihr in jeder Datei unterhalb von /etc/ nach dem Begriff max_memory.

wenn ihr hingegen alle Dateien innerhalb eines Ordners finden wollt, die einen bestimmten Begriff enthalten, geht das mit

grep -Ril "suchstring" <pfad>

Alternative

grep -rnw '/pfad/' -e "text"

Alternativ kann auch das Komamdnozeilentool ack genutzt werden.

ack 'suchstring'

umgekehrter FAll: gib alles aus einer Datei aus, außer Zeilen mit

den umgekehrten Fall, dass man alles ausgegeben haben will, außer die Zeilen die etwas bestimmtes enthalten, realisiert man mit

grep -v 'max_memory' /etc/*

Damit werden alle Zeilen ausgegeben, außer die, welche max_memory enthalten.

Textdateien, die nicht sauber interpretiert werden

Sehr störend sind unsauber gesetzte Textdateien, die non-printing-characters enthalten, die man mit einem Befehl wie

cat <datei>

nicht sehen kann, jedoch die Interpretation der Datei durch andere Kommnandos oder Programme durcheinander bringen. Solche Zeichen sind biespielswiese die Zeilenumbrüche verschiedener Betriebssysteme (Windows benutzt andere Zeilenumbrüche als Linux und diess wiederum andere als Mac OS X). Solche non-printing-characters kann man sich jedoch markieren lassen über

cat -vet <datei>

Merkspruch: If your cat is ill, you take it to the vet.

Ausgaben sortieren mit sort

mit sort lassen sich die Ausgaben von Befehlen oder die Zielen von DAteien nachträglich sortieren. So ist es beispieslweise möglichsich die Ausgabe der Datei /etc/passwd nach alphabetischer Reihenfolge der Benutzernamen anzeigen zu lassen über

cat /etc/passwd | sort

Wollen wir es in der andren REihenfolge, also von Z nach A, dann geben wir an

cat /etc/passwd | sort -r

Ich sortiere eigentlich so gut wie alle meine Ausgaben unter Linux mit sort, außer die Ausgbae von ls -la, also der Anzeige von Dateien in einem Verzeihcnis, diesen sortiere ich einfach über den PArameter

ls -lart

denn sortiert dann automatisch von obne (älteste Datei) nach unten (neueste Datei), so dass ich am Ende des kommandozeilenoutputs die neuesten Dateien stehen habe, etwa die aktuellste Version einer .log-Datei.

Arbeiten mit regulären Ausdrücken und sed

Als Ergänzung, um die regulären Ausdrücke aus diesem kapitel zu verstehen, solltet ihr meinen Post über reguläre Ausdrücke lesen bzw. darin als Referenz nachschlagen.

Die Linux-Binary sed nutze ich sehr gerne in Verbindung mit regulären Ausdrücken, denn mit sed ist es möglich, nach Zeichenketten zu suchen, die in einen regulären Ausdruck passen, und diese dann durch eine andere Zeichenkette zu ersetzen.

Somit wäre es beispielsweise möglich, die Doppelpunkte (:) zwischen den Einträgen in der /etc/passwd zu ersetzen, indem man sagt

sed -e 's/:/-/g'

Wie sit das kommando zu lesen? der PArmaeter -e sagt dem Kommando sed, dass jetzt ein regulärer Ausdruck kommt (statt einer bloßen „dummen“ Zeichenkette), /s/ steht für substitute, sagt also dem Kommando sed, dass es nach der Zeichenkette, die nach dem ersten SChrägstrich (/) kommt, suchen soll, und diese durch die Zeichenkette ersetzen soll, die nach dem zweiten Schrägstrich kommt. Wir ersetzen also den Doppelpunkt durch den Bindestrich. und /g steht für global, das bedeutet, wir wollen nicht nur die allererste Zeichenkette, die gefunden wird, ersetzen, sondern alle Zeichenketten, die auf diese Art und Weise gefunden werden.

In 99% aller Fälle werdet ihr das Kommando sed in folgendem Format verwenden:

sed -e 's/<suche nach dem>/<ersetze mit dem>/g

Zeichen ersetzen oder löschen mit tr

tr funtioniert ähnlich wie sed, also es sucht nach Zeichenketten und ersetzt oder löscht diese. Beispielsweise ersetzt das kommando

tr a o <datei>

alle klein geschriebenen a’s in einer Datei durch klein geschrieben o’s.

Nun werdet ihr euch denken: „Ja gut, dafür hätte ich aber auch sed nutzen können, warum also tr überhaupt nutzen?“. Naja, mit tr ist es sehr leicht, mehrfache Ersetzungen zu beschreiben, beispielsweise ersetzt das kommando

tr mo Tx <datei>

alle klein geschriebenen m durch groß geschriebene T’s und alle klein greschriebenn o’s durhc klein geschriebene x. Dafür hättet ihr eigentlich zweimal das sed-Kommando hintereinander ausführen müssen.

Immer noch nicht überzeugt? dann lasst uns mal alle KLeinbuchstaben zu Großbuchstbaen umwandeln.

tr [:lower:] [:upper:]

doppelte Zeilen entfernen mit uniq

DAs Tool uniq wird ursprünglich dazu verwendet, um doppelt oder mehrfach vorkommende Zeilen in einer Datei zu entfernen. uniq würde als aus einer Datei mit Inhalt

 

a
a
a
b
b
b
c
c
c
cc

folgendes:

a
b
c
cc

Jedoch funktioniert es leider nicht bie einer Datei wie der folgenden:

a
b
a
b
cc
c
a
c
b
a
c

an dieser Datei würde uniq nämlich leider nichts ändertn, da uniq nur aufeinander folgende doppelte Zeilen entfernt. Dieses Problem könnt ihr lösen mit dem kommando sort, welches wir weiter oben schon kennegelernt haben. DAs Kommando sort bringt die gleichlautenden Zeilen untereinander und dann kann uniq seinen Job machen.

sort <datei> | uniq

Die Anzahl der Redundanzen, also der Vorkommnisse einer Zeile, könnt ihr euch ausgeben lasen über den PArameter -c. Sprich das KOmmando

sort <datei> | uniq -c

würde bei dieser Datei

a
a
a
b
b
b
c
c
c
cc

ausgeben

3 a
3 b
3 c
1 cc

Der Parameter -u hingegen gibt euch nur die Zeilen aus, die nicht wiederholt werden, das kommando

sort <datei> | uniq -u

führt also zur Ausgabe

cc

Mit anderen Tools wie beispielsweise grep, tr, cut und awk kombiniert könnt ihr euch natürlich vorstellen, dass ihr mit uniq auch doppelte Spalten oder Wörter entfernen könnt, indem ihr erst mit grep, cut und awk die Spalten von dem restlichen Inhalt der Datei isoliert, so dass nur noch die Wörter bzw. Spalten in dne Zeilen vorkommen, und ihr diese doppelten dann entsprechend entfernen könnt. Wie auch immer, das funktioniert natürlich nur, wenn man es sich leisten kann, die doppelten Einträge erst in einzelne Zeilen zu extrahieren. WEnn die Originaldatei jedoch unangetastet bleiben soll, müsst ihr Skriptsprachen oder die Suchen und Erstezen Funktion von Texteditoren verwenden. Für das einfache Entfernen von doppelten, direkt hintereinander geschrieben Worten in ein und derselben Zeile jedoch kann euch noch dieser sed Befehl helfen.

Dateiversionen vergleichen mit sdiff

wenn ihr zwei Versionen einer Textdatei vergleichen wollt, um die Unterschiede in den Dateien zu sehen, empfehle ich euch sdiff. Beide Dateien werdne gegenübergestellt und ihr seht die Änderungen sofort.

sdiff <datei1> <datei2>

Die beiden Versionen werden dann gegenübergestellt und in der Mitte wird durch ein Zeichen (Gutter genannt) angedeudetet, ob die Zeilen gleich oder unterschiedlich sind

whitespaceZeilen sind gleich oder Änderungen wurdne ignroiert dank der –ignore option
|Zeilen unterschiedne sich, beide sind unvollständig.
<nur die erste Datei enthält die Zeile
>nur die zweite Datei enthält die Zeile
(nur die erste Datei enthält die Ziele, aber der Unterschied wird ignoriert
)nur die zweite Datei enthält die Zeile, aber der Unterschied wird ignoriert.
\die Zeilen untershciedne sich und die erste Zeile ist unvollständig
/die Zeilen unterscheidne sich und eie zweite Zeile ist unterschiedlich

Dateiversionen aktualisieren mit patch und merge

Wenn zwei Personen an der selben Textdatei arbeiten, möchte Person A seine Änderungen PErson B schicken, damit PErson B mit den Implementierungen von PErson A weiterarbeiten kann. Umgekehrt kann Person B seine Ämnderungen Person A schicken, so dass beide auf dem gleichen STand sind.

Person A möchte jetzt Person B seine Änderungen schicken, dazu hat PErson A die letzte Dateiversion, von der beide PErsonen aus angefangen haben zu arbeiten, eine Kopie namens datei1. Und die aktuelle Version, die er bearbeitet hat, ist datei2. Jetzt erzeugt Person A erstmal eine .patch-Datei, die er Person B schicken kann, über:

diff -u <datei1> <datei2> > persona.patch

Wir vergleichen also datei1 mit datei2 und speichern die unterschiede von von datei2 gegenüber datei1 in einer .patch-datei. Person A schickt nun Person B diese .patch-Datei zu.

Nun macht Person B ebenfalls eine .patch-Datei von seiner datei1 über

diff -u <datei1> <datei2> > personb.patch

und schickt diese Version Person A. Beide Personen kommen nun auf den selben Stand, indem sie zusammen auf datei1 beide .patch-DAteien einspielen. Sowohl Person A als auch Person B geben also ein

patch < persona.patch
patch < personb.patch

die ursprüngliche Version von Datei1 wird also mit den Änderungen der beiden Personen gepatcht und somit wieder auf einen gemeinsamen STand gebracht. Dateinamen müssen nicht angegeben werden, da der Name der Orignaldatei <datei1> in den .patch-DAteien hinterlegt ist. Problem ist, dass wenn PErson B eine Änderung in einer Zeile macht, die Person A ebenfalls bearbeitet hat, überschreibt der Patch von PErson B die Änderungen von Person A.

Einige würden jetzt vielleicht argumentieren, dass dieser Prozess ziemlich kompliziert ist, vor allem wenn nicht nur zwei, sondern mehree Personen zusammen an einer Datei arbeiten. Undd as ist auch wirklich so. Linux bietet hierzu noch eine bessere Binary namens merge. Merge nimmt einfach nur die drei Dateien – die Original <datei1>, die <datei2> von Person A und die <datei2> von Person B und führt ide Änderungen aus <datei2> von Person A und <datei2> von Person B automatisch in <datei1> über. Der Vorteil an merge gegenüber patch ist außerdem, dass merge Konflikte erkennt. Wenn also Person B die gleihce Zeile bearbeitet hat wie PErson A, wird eine Warnung ausgegebn nach dem Motto: „einigt euch doch zuerst mal, welche Änderung übernommen bzw. die wie Änderungen zusammengeführt werden sollen“.

Das kommando würde so gehen

merge <datei1> <datei2_persona> <datei2_personb>

Alle Logs in einem Verzeichnis verfolgen

Um Änderungen an mehreren Logdateien in einem Verzeichnis zu folgen – außer den komprimierten Log-DAteien mit einer Dateiendung wie .gz, kann folgendes kommando genutzt werden

tail -f `ls -l /var/logs/myLog* |grep -v .gz$`

Textdateien spalten- oder zeilenweise zusammenführen mit paste

Nehemn wir an, ihr habt zwei TExtdateien, die mehrere Zeilen enthatlen, und diese Zeilen wollt ihr in einer Art Tabellenstruktur zusammenführen. Also die Zeilen von Datei 1 werden die erste Spalte und die Zeilenvon Datei 2 werden die zweite Spalte. DAs komamndo

paste -d: <datei1> <datei2>

führt die Zeilen von Datei 1 und Datei 2 so zusammen, dass die Spalten durch einen Doppelpunkt (:) voneinander getrennt werden

<datei1_zeile1>:<datei2_zeile1>
<datei1_zeile2>:<datei2_zeile2>
<datei1_zeile3>:<datei2_zeile3>

Ihr könnt mit paste aber auch mehrer Zeilen zu einer zusammenfügen. Beispiel, wir haben eine Text Datei mit den Adressdaten mehrerer Personen

Herr
Hubert
Holzmann
0170333333
hubert.holzmann@web.de

Frau
Ute
Ulbricht
0170444444
ute.ulbricht@web.de

Herr
Axel
Mustermann
0170555555
axel.mustermann@web.de

DAnn könnt ihr die Adressdaten jeder Person in eine Spalte kriegen über

< <datei>.txt paste - - - - -

und erhaltet als Ausgabe

Herr Hubert Holzmann 017033333 hubert.holzmann@web.de
Frau Ute Ulbricht 01704444 ute.ulbricht@web.de
Herr Axel Mustermann 01705555 axel.mustermann@web.de

und mit dem PArmaeter -d könnt ihr stattt Leerzeichen auf beispielswiese Kommata oder andere Trennzeichen benutzen, um die Spalten voneiannder abzutrennen. WEnn ihr hierfür beispielsweise Kommata nehmt, könnt ihr die Datensätze so nachher über ein INSERT INTO-Statement in eine Datenbank laden.

Windows-PowerShell-Textverarbeitung

grep unter Powershell mit sls

auch die PowerShell hat eine grep-Funktionalität, mit dessen Hilfe man Text aus der Ausgabe eines komamndos filtern kann. dAs kommando heißt select-string, kurz sls. Wenn ich beispielsweise aus dem kommando netstat-ab alle Verbindungen über einen bestimmten Port rausfinden möchte, beispielsweise 4903, dann gebe ich ein

netstat -ab | sls 4903

häufig möchte ich noch Zeilen sehen, die vor oder nach den gefundenen Zeilen kommen. Wenn ich möchte, dass ich die 5 Zeilen vor und nach der gefundenen Zeile anzeigen lasse, dann gebe ich ein

netstat -ab | sls 4903 -Context 5,5

wollt ihr hingegen nicht die passenden Zeilen ausgeben, sondern nach DAteien suchen, die einen bestimmten TExt enthalten, dann geht das über

Get-ChildItem -Recurse filespec | Select-String pattern | Select-Object -Unique Path
ls -r filespec | sls pattern | select -u Path

head und tail

Auch die Unix/Linux-Kommandos head und tail lassen sich unter Windows mit Hilfe der PowerShell ersetzen. Dazu piped man die Ausgabe des vorgägnerkommandos an das cmdlet select. Die folgende Zeile gibt nur die ersten 10 Dienste auf dem Windows-system aus

get-process | select -first 10

Befehlsausgabe in Windows-FEnster anzeigen mit out-gridview

ein meiner Meinung nach sehr cooles Feature ist die Möglichkeit, sich eine Befehlsausgabe in einem übersichtlichen Windows-Fenster anzeigen zu lassen. Dazu muss allerdings auf dem Rechner die Powershell ISE zwingend installiert sein, was jedoch meistnes der Fall ist.

awk Alternative mit split

wie auch unter Linux wollten wir auch mit der Powershell verschiedene Saplten einer Datei, beispielsweise aus einem .csv-Dokument, extrahieren können. DAzu nutzen wir in der Powershell das split-Tool.

Nehmen wir an, wir haben eine .csv-Dtei, in welcehr die einzlenen Spalten mit kommas getrennt sind. DAnn bekommen wir die zweite Spalte dieser Datei extrahiert über

Get-Content <.csv-Datei> | %{ $_.Split(',')[1]; }

ihr seht also, innerhalb der Split-Satements gebt ihr das Trennzeichen und die Spalte an, die ihr haben wollt. Ebenfalls fällt auf, dass die zweite Spalte mit der Ziffer 1 angegeben wird, das heißt, Split fängt bei 0 an, zu zählen.

 

Mit Split könnt ihr auch eine Spatle, die nur Zahlenwerte enthält, zusammenzählen. WEnn unsere zweite Spalte nur Zahlenwerte enthält, bekommen wir die Summe dieser Spalte über

Get-Content <.csv-Datei> | %{ [int]$total+=$_.Split(',')[1]; } ; Write-Host "Summe: $total"

Und natürlich könnenw ri auch wieder mit regulären Ausdrücken arbeiten. Wir geben einen DAtensatz nur dann aus, wenn die letzte Saptle einen Kleinbuchstaben enthält

Get-Content <csv-Datei> | %{ if ($_.Split(',')[-1] -match "[a-z]") { $_; } }

sed Alternative

Auch eine Alternative zu sed gibt es in der Powershell, mit der wir Zeichen ersetzen können. Auch hier können wir wieder mit regulären Ausdrücken arbeiten

gc <datei> | %{$_ -replace <regulärer Ausdruck>,”replace”}

 

Ein Kommando auf mehrere Dateien in richtiger Reihenfolge

Herausforderung: In meinem Beispiel versuche ich, ein System zu patchen, in welchem verschiedene Dateien abhängig von ihrem Patchlevel in der richtigen Reihenfolge entpackt werden müssen. Der Extraktbefehl ist für alle Dateien derselbe. Anstatt diesen also jedesmal neu einzutippen, möchte ich diesen nur einmal schreiben.

In diesem Projekt verwende ich absichtlich nicht die LinuxKommandozeilentools tr, cut, sed und awk, die ich oben schonmal gezeigt habe, um euch den Lösungsansatz via Texteditor und Excel zu zeigen.

Als erstes exportiere ich mir eine Liste aller Dateien. Die zu entpackenden .SAR-Archive habe ich mir hierzu bereits in ein extra Verzeichnis heruntergeladen, von dem aus ich mir über das Linux-Kommando

ls -la > files.txt

eine Liste erstellen lasse. Windows-Alternatie ist das Kommando dir. Die files.txt lade ich mir mittels SCP oder SFTP vom Linux Server auf meinen Windows-Arbeitsplatz herunter. So sieht meine files.txt derzeit aus.

total 637912
drwxr-xr-x  2 root   root        4096 Jan 22 12:07 .
drwxrwxrwx 17 s4hadm sapsys      4096 Jan 22 11:55 ..
-rw-r--r--  1 root   root           8 Jan 22 11:59 R3check_22-80000699
-rw-r--r--  1 root   root     3957559 Jan 22 11:59 R3check_22-80000699.SAR
-rw-r--r--  1 root   root          15 Jan 22 11:59 R3ldctl_26-80000698
-rw-r--r--  1 root   root     1916846 Jan 22 11:59 R3ldctl_26-80000698.SAR
-rw-r--r--  1 root   root           7 Jan 22 11:59 R3load_23-80000698
-rw-r--r--  1 root   root     3473641 Jan 22 11:59 R3load_23-80000698.SAR
-rw-r--r--  1 root   root           8 Jan 22 11:59 R3szchk_19-80000698
-rw-r--r--  1 root   root     1789191 Jan 22 11:59 R3szchk_19-80000698.SAR
-rw-r--r--  1 root   root           5 Jan 22 11:59 R3ta_28-80000699
-rw-r--r--  1 root   root     2115907 Jan 22 11:59 R3ta_28-80000699.SAR
-rw-r--r--  1 root   root           8 Jan 22 11:59 R3trans_33-80000699
-rw-r--r--  1 root   root     4021570 Jan 22 11:59 R3trans_33-80000699.SAR
-rw-r--r--  1 root   root          14 Jan 22 12:06 SAPCRYPTOLIBP_8447-20011697
-rw-r--r--  1 root   root     2361623 Jan 22 12:06 SAPCRYPTOLIBP_8447-20011697.SAR
-rw-r--r--  1 root   root          21 Jan 22 12:03 SAPEXEDB_23-80000698
-rw-r--r--  1 root   root    14195185 Jan 22 11:56 SAPEXEDB_23-80000698.SAR
-rw-r--r--  1 root   root          20 Jan 22 11:56 SAPEXE_23-80000699
-rw-r--r--  1 root   root   298932912 Jan 22 11:56 SAPEXE_23-80000699.SAR
-rw-r--r--  1 root   root           9 Jan 22 11:56 ccmagent_22-80000699
-rw-r--r--  1 root   root    23276616 Jan 22 11:56 ccmagent_22-80000699.sar
-rw-r--r--  1 root   root          18 Jan 22 12:00 dw_33-80000699
-rw-r--r--  1 root   root   157536215 Jan 22 12:00 dw_33-80000699.sar
-rw-r--r--  1 root   root          17 Jan 22 11:59 dw_utils_28-80000699
-rw-r--r--  1 root   root     6798429 Jan 22 11:59 dw_utils_28-80000699.sar
-rw-r--r--  1 root   root           9 Jan 22 11:56 enserver_33-80000699
-rw-r--r--  1 root   root     8585008 Jan 22 11:56 enserver_33-80000699.sar
-rw-r--r--  1 root   root           0 Jan 22 12:07 files.txt
-rw-r--r--  1 root   root          50 Jan 22 12:06 igsexe_10-20007790
-rw-r--r--  1 root   root    40456133 Jan 22 12:06 igsexe_10-20007790.sar
-rw-r--r--  1 root   root          27 Jan 22 12:06 igshelper_4-10010245
-rw-r--r--  1 root   root    62964419 Jan 22 12:06 igshelper_4-10010245.sar
-rw-r--r--  1 root   root          17 Jan 22 11:56 lib_dbsl_18-80000698
-rw-r--r--  1 root   root      729272 Jan 22 11:56 lib_dbsl_18-80000698.sar
-rw-r--r--  1 root   root           7 Jan 22 12:01 librfc_31-80000699
-rw-r--r--  1 root   root    10317409 Jan 22 12:01 librfc_31-80000699.sar
-rw-r--r--  1 root   root           8 Jan 22 11:59 saphttp_30-80000699
-rw-r--r--  1 root   root     2537721 Jan 22 11:59 saphttp_30-80000699.sar
-rw-r--r--  1 root   root           9 Jan 22 12:03 sapnwrfc_24-80000699
-rw-r--r--  1 root   root     3331542 Jan 22 12:03 sapnwrfc_24-80000699.sar
-rw-r--r--  1 root   root           9 Jan 22 12:03 startsap_27-80000699
-rw-r--r--  1 root   root       25529 Jan 22 12:03 startsap_27-80000699.sar
-rw-r--r--  1 root   root           3 Jan 22 11:59 tp_33-80000699
-rw-r--r--  1 root   root     3770458 Jan 22 11:59 tp_33-80000699.sar

Hierbei gibt es einmal dateien ohne .sar und einmal mit .sar am Ende. Die Dateien ohne Endung sind nutzlos, das sind nur Labels, die beschreiben, was in den DAteien drin ist. Eine bessere Liste ohne diese Dateien könnte ich mir beispielsweise mit dem Linux kommando find ausgeben lassen. Da es einmal mit Dateien mit großem .sar und einmal mit kleinem .SAR gibt, würde ich eintippen.

find <verzeichnis> -name '*.sar' -o -name '*.SAR'

Somit hätte ich dann, wenn ich es wollte, eine Liste ohne die Label-Dateien.

Als erstes lösche ich einfach über Notepad++ die überflüssigen Spalten wie biespielsweise die Linux RWX-Berehcitugngen, File Owner, Dateigröße und Timestamp. Dazu markiere ich einfach mit gedrückter Alt-Taste die Spalten und lösche sie. Dann lösche ich noch in der übrig gebleibeneen letzten Spalte die Zeilen für die files.txt selbst und die Einträge für das aktuelle Verzeichnis (.) sowie das übergeordnete (..). Meine files.txt sieht jetzt nur noch so aus:

R3check_22-80000699
R3check_22-80000699.SAR
R3ldctl_26-80000698
R3ldctl_26-80000698.SAR
R3load_23-80000698
R3load_23-80000698.SAR
R3szchk_19-80000698
R3szchk_19-80000698.SAR
R3ta_28-80000699
R3ta_28-80000699.SAR
R3trans_33-80000699
R3trans_33-80000699.SAR
SAPCRYPTOLIBP_8447-20011697
SAPCRYPTOLIBP_8447-20011697.SAR
SAPEXEDB_23-80000698
SAPEXEDB_23-80000698.SAR
SAPEXE_23-80000699
SAPEXE_23-80000699.SAR
ccmagent_22-80000699
ccmagent_22-80000699.sar
dw_33-80000699
dw_33-80000699.sar
dw_utils_28-80000699
dw_utils_28-80000699.sar
enserver_33-80000699
enserver_33-80000699.sar
igsexe_10-20007790
igsexe_10-20007790.sar
igshelper_4-10010245
igshelper_4-10010245.sar
lib_dbsl_18-80000698
lib_dbsl_18-80000698.sar
librfc_31-80000699
librfc_31-80000699.sar
saphttp_30-80000699
saphttp_30-80000699.sar
sapnwrfc_24-80000699
sapnwrfc_24-80000699.sar
startsap_27-80000699
startsap_27-80000699.sar
tp_33-80000699
tp_33-80000699.sar

So wird die Datei nun in einer tabellenkalkulationssoftware wie beispielsweise Microsoft Office Excel geöffnet. Ich möchte die Dateien nämlich nach dem Patchlevel, welches ich weiter oben an einigen Stellen fett markiert habe (nach dem Unterstrich), sortieren. Dazu muss ich das Patch Level der Dateien erstmal in eine extra Spalte bekommen. Ich gebe also beim ÖFfnen der Datei an, dass die Spalten durch einen Trenner getrennt sind

2016-01-22_13h13_13

und wähle dann bei Zeichen als erstes den Unterstrich

2016-01-22_13h14_12

Jetzt haben wir das Patchlevel in einer extra Spalte. Über die Schaltfläche sortieren kann ich die Dateien un nach PAtchlevel sortieren, somit stehen sie in der richtigen Reihenfolge.

2016-01-22_13h42_04

Würde ich jetzt noch wollen, dass das PAtchlevel auch noch von der Zahl hinter dem Bindestrich (-) getrennt wird, würde ich in der Registerkarte Daten nochmal in der Gruppe Datentools auf das Icon TExt in Spalten klicken und die Trennung nochmal mit dem Bindestrich durchführen, ist aber hier unnötig.

2016-01-22_14h06_33

Nun kopiere ich die beiden Spalten und füge sie wieder in ein leeres Dokument ein, welches ich mit dem Editor Notepad++ wieder bearbeite. Ich erhalte wieder die Dateinamen, jedoch ohne den Unterstrich.

2016-01-22_13h43_43

diesen muss ich jetzt wiederherstellen. Zwischen dem eigentlichen Dateinamen und dem PAtchlevel sind keine Leerzeichen, sondern Tabstopps. Diesen Tabstopp markiere ich einfach mit der Maus und kopiere ihn mir in die Zwischenablage. Dann gehe ich über das Menü von Notepad++ auf Search / Replace und füge bei Find what den Tabstopp ein und gebe bei REplace with den Unterstrich ein.

2016-01-22_13h44_59

Jetzt habe ich meine Dateinamen wieder sauber beisammen.

2016-01-22_13h45_30

Nun müssen vor und hinter die Dateinamen Textschnipsel, die später das Kommando ausmachen. Dazu halte ich die Alt-Taste gedrückt und markiere alle Zeilen des Dokuments, die ich bearbeiten möchte. Dabei markiere ich mit der MAus so, dass ich vor allen Zeilen einen Cursor habe.

2016-01-22_13h47_16

nun kann ich vor allen Dateinamen meinen Befehl eintippen. Danach setze ich mir mit gedrückter Alt-Taste einen Cursor hinter alle Dateinamen, wie im Bild angedeutet.

2016-01-22_13h48_52

Jetzt kann ich die abshcließenden PAramter der Kommandos hinter alle Dateinamen tippen.

2016-01-22_13h50_04

Und nun zu guter letzt kriegen wir mit Search and Replace die überflüssigen LEerzeichen weg, indem wirzwei Leerzeicehn mit nichts ersetzen lassen. Da die Anzahl der Leerzeicehn zwischen den DAteinamen und dem -R Parameter in vielen Fällen ungerade ist, sind dann die mesiten Zeilen schon richitg getrennt.

2016-01-22_13h52_01

2016-01-22_13h53_22

Jedoch, wie im SCreenshot ersichtlich, ein paar Zeilen gab es dann doch, wo die Anzahl der Leerezciehn zwischen Dateiname und -R gerade war und daher kein LEerzeichen mehr dazwischen ist. Also gehe ich im zweiten Schritt her und ersetze „.sar-R“ durch „.sar -R“. Damit passen dann die Leerzeichen wieder bei allen .sar-Dateien.

Unterschiedliche Versionen einer Datei vergleichen.

Folgende Herausforderung

Ich habe eine .TSK-Datei, welche Datenpakete entählt, die ein Interpretertool abarbeiten muss. DAs Interpretertool merkt sich über die .TSK-Datei, welche Datenpakete es noch abarbeiten muss und welche schon fertig sind. Die originale .TSK-Datei in dem Zustand, in welchem alle Datenpakete noch abgeabreitet werden müssen, sieht so aus (nur ein Ausschnitt von 100 Zeilen)

T /AIF/BDC_IF_CONF C xeq
D /AIF/BDC_IF_CONF I xeq
M /AIF/BDC_IF_CONF C xeq
P /AIF/BDC_IF_CONF~0 C xeq
U /AIF/BDC_IF_CONF C xeq
T /AIF/BDC_IF_GEN C xeq
D /AIF/BDC_IF_GEN I xeq
M /AIF/BDC_IF_GEN C xeq
P /AIF/BDC_IF_GEN~0 C xeq
U /AIF/BDC_IF_GEN C xeq
T /AIF/BDC_ST_CONF C xeq
D /AIF/BDC_ST_CONF I xeq
M /AIF/BDC_ST_CONF C xeq
P /AIF/BDC_ST_CONF~0 C xeq
U /AIF/BDC_ST_CONF C xeq
T /AIF/BDC_ST_GEN C xeq
D /AIF/BDC_ST_GEN I xeq
M /AIF/BDC_ST_GEN C xeq
P /AIF/BDC_ST_GEN~0 C xeq
U /AIF/BDC_ST_GEN C xeq
T /AIF/CIFPP_SS_AS C xeq
D /AIF/CIFPP_SS_AS I xeq
M /AIF/CIFPP_SS_AS C xeq
P /AIF/CIFPP_SS_AS~0 C xeq
U /AIF/CIFPP_SS_AS C xeq
T /AIF/CIFPP_TJSEL C xeq
D /AIF/CIFPP_TJSEL I xeq
M /AIF/CIFPP_TJSEL C xeq
P /AIF/CIFPP_TJSEL~0 C xeq
U /AIF/CIFPP_TJSEL C xeq
T /AIF/DOCU C xeq
D /AIF/DOCU I xeq
M /AIF/DOCU C xeq
P /AIF/DOCU~0 C xeq
U /AIF/DOCU C xeq
T /AIF/DOCUT C xeq
D /AIF/DOCUT I xeq
M /AIF/DOCUT C xeq
P /AIF/DOCUT~0 C xeq
U /AIF/DOCUT C xeq
T /AIF/DOCU_TAB C xeq
D /AIF/DOCU_TAB I xeq
M /AIF/DOCU_TAB C xeq
P /AIF/DOCU_TAB~0 C xeq
U /AIF/DOCU_TAB C xeq
T /AIF/DOCU_TABT C xeq
D /AIF/DOCU_TABT I xeq
M /AIF/DOCU_TABT C xeq
P /AIF/DOCU_TABT~0 C xeq
U /AIF/DOCU_TABT C xeq
T /AIF/ERR_APP C xeq
D /AIF/ERR_APP I xeq
M /AIF/ERR_APP C xeq
P /AIF/ERR_APP~0 C xeq
U /AIF/ERR_APP C xeq
T /AIF/ERR_INF C xeq
D /AIF/ERR_INF I xeq
M /AIF/ERR_INF C xeq
P /AIF/ERR_INF~0 C xeq
U /AIF/ERR_INF C xeq
T /AIF/LOGSYST C xeq
D /AIF/LOGSYST I xeq
M /AIF/LOGSYST C xeq
P /AIF/LOGSYST~0 C xeq
U /AIF/LOGSYST C xeq
T /AIF/NEWDEVPROJS C xeq
D /AIF/NEWDEVPROJS I xeq
M /AIF/NEWDEVPROJS C xeq
P /AIF/NEWDEVPROJS~0 C xeq
U /AIF/NEWDEVPROJS C xeq
T /AIF/NEWDEVPROJT C xeq
D /AIF/NEWDEVPROJT I xeq
M /AIF/NEWDEVPROJT C xeq
P /AIF/NEWDEVPROJT~0 C xeq
U /AIF/NEWDEVPROJT C xeq
T /AIF/NEWDEV_IDS C xeq
D /AIF/NEWDEV_IDS I xeq
M /AIF/NEWDEV_IDS C xeq
P /AIF/NEWDEV_IDS~0 C xeq
U /AIF/NEWDEV_IDS C xeq
T /AIF/NEWDEV_IDST C xeq
D /AIF/NEWDEV_IDST I xeq
M /AIF/NEWDEV_IDST C xeq
P /AIF/NEWDEV_IDST~0 C xeq
U /AIF/NEWDEV_IDST C xeq
T /AIF/PERS_RP_MSG C xeq
M /AIF/PERS_RP_MSG C xeq
P /AIF/PERS_RP_MSG~0 C xeq
U /AIF/PERS_RP_MSG C xeq
T /AIF/PERS_RTCFGR C xeq
D /AIF/PERS_RTCFGR I xeq
M /AIF/PERS_RTCFGR C xeq
P /AIF/PERS_RTCFGR~0 C xeq
U /AIF/PERS_RTCFGR C xeq
T /AIF/PERS_RTCFGT C xeq
D /AIF/PERS_RTCFGT I xeq
M /AIF/PERS_RTCFGT C xeq
P /AIF/PERS_RTCFGT~0 C xeq
U /AIF/PERS_RTCFGT C xeq
T /AIF/POC_C_CFGAD C xeq

der Eintrag ganz hinten, xeq, gibt an, dass die Datenpakete noch abgearbeitet werden müssen.

Nun sieht die Datei nach einer WEile vielleicht so aus:

T /AIF/BDC_IF_CONF C err
D /AIF/BDC_IF_CONF I err
M /AIF/BDC_IF_CONF C xeq
P /AIF/BDC_IF_CONF~0 C xeq
U /AIF/BDC_IF_CONF C xeq
T /AIF/BDC_IF_GEN C xeq
D /AIF/BDC_IF_GEN I err
M /AIF/BDC_IF_GEN C err
P /AIF/BDC_IF_GEN~0 C err
U /AIF/BDC_IF_GEN C err
T /AIF/BDC_ST_CONF C xeq
D /AIF/BDC_ST_CONF I xeq
M /AIF/BDC_ST_CONF C xeq
P /AIF/BDC_ST_CONF~0 C xeq
U /AIF/BDC_ST_CONF C err
T /AIF/BDC_ST_GEN C err
D /AIF/BDC_ST_GEN I err
M /AIF/BDC_ST_GEN C err
P /AIF/BDC_ST_GEN~0 C err
U /AIF/BDC_ST_GEN C xeq
T /AIF/CIFPP_SS_AS C xeq
D /AIF/CIFPP_SS_AS I xeq
M /AIF/CIFPP_SS_AS C xeq
P /AIF/CIFPP_SS_AS~0 C err
U /AIF/CIFPP_SS_AS C err
T /AIF/CIFPP_TJSEL C err
D /AIF/CIFPP_TJSEL I err
M /AIF/CIFPP_TJSEL C err
P /AIF/CIFPP_TJSEL~0 C err
U /AIF/CIFPP_TJSEL C xeq
T /AIF/DOCU C xeq
D /AIF/DOCU I xeq
M /AIF/DOCU C xeq
P /AIF/DOCU~0 C xeq
U /AIF/DOCU C xeq
T /AIF/DOCUT C err
D /AIF/DOCUT I err
M /AIF/DOCUT C err
P /AIF/DOCUT~0 C err
U /AIF/DOCUT C err
T /AIF/DOCU_TAB C err
D /AIF/DOCU_TAB I err
M /AIF/DOCU_TAB C err
P /AIF/DOCU_TAB~0 C xeq
U /AIF/DOCU_TAB C xeq
T /AIF/DOCU_TABT C xeq
D /AIF/DOCU_TABT I xeq
M /AIF/DOCU_TABT C xeq
P /AIF/DOCU_TABT~0 C xeq
U /AIF/DOCU_TABT C err
T /AIF/ERR_APP C err
D /AIF/ERR_APP I err
M /AIF/ERR_APP C err
P /AIF/ERR_APP~0 C err
U /AIF/ERR_APP C err
T /AIF/ERR_INF C err
D /AIF/ERR_INF I xeq
M /AIF/ERR_INF C xeq
P /AIF/ERR_INF~0 C xeq
U /AIF/ERR_INF C xeq
T /AIF/LOGSYST C xeq
D /AIF/LOGSYST I err
M /AIF/LOGSYST C err
P /AIF/LOGSYST~0 C err
U /AIF/LOGSYST C err
T /AIF/NEWDEVPROJS C err
D /AIF/NEWDEVPROJS I err
M /AIF/NEWDEVPROJS C err
P /AIF/NEWDEVPROJS~0 C err
U /AIF/NEWDEVPROJS C xeq
T /AIF/NEWDEVPROJT C xeq
D /AIF/NEWDEVPROJT I xeq
M /AIF/NEWDEVPROJT C xeq
P /AIF/NEWDEVPROJT~0 C xeq
U /AIF/NEWDEVPROJT C xeq
T /AIF/NEWDEV_IDS C err
D /AIF/NEWDEV_IDS I err
M /AIF/NEWDEV_IDS C err
P /AIF/NEWDEV_IDS~0 C err
U /AIF/NEWDEV_IDS C ok
T /AIF/NEWDEV_IDST C ok
D /AIF/NEWDEV_IDST I ok
M /AIF/NEWDEV_IDST C ok
P /AIF/NEWDEV_IDST~0 C ok
U /AIF/NEWDEV_IDST C err
T /AIF/PERS_RP_MSG C err
M /AIF/PERS_RP_MSG C xeq
P /AIF/PERS_RP_MSG~0 C xeq
U /AIF/PERS_RP_MSG C ok
T /AIF/PERS_RTCFGR C ok
D /AIF/PERS_RTCFGR I ok
M /AIF/PERS_RTCFGR C ok
P /AIF/PERS_RTCFGR~0 C ok
U /AIF/PERS_RTCFGR C xeq
T /AIF/PERS_RTCFGT C xeq
D /AIF/PERS_RTCFGT I xeq
M /AIF/PERS_RTCFGT C xeq
P /AIF/PERS_RTCFGT~0 C ok
U /AIF/PERS_RTCFGT C ok
T /AIF/POC_C_CFGAD C ok

Status ok beduetet, dass das PAket feritg abgeabreitet wurde, STatus err beduetet, dass das Paket fehlerhaft bearbeitet wurde und daher ebenfalls nochmal abgearbeitet werden muss, jedoch anders als bei xeq.

Ich möchte jetzt zwei SAchen, ich möchte zum einen eine Übersicht haben, welche pakete noch nicht sauber durchgearbeitet wurden, und zum anderen möchte ich eine Datei mit allen Pakleten, die Status xeq oder err haben.

In dem FAll ist es sehr einfach: alle Einträge sind gleich sortiert und in beiden Dateien sind immer alle Einträge vorhanden. Mit einem Tool wie winmerge lade ich die beiden Dateien und lasse sie vergleichen. Die Zeilen, die sich untershcieden, werden mir einfach angezeigt.  So sehe ich in einer Übersicht, welche Pakete noch abgearbeitet werden müssen. Links ist die Liste mit den err und ok statuscodes, rechts ist die Originaldatei.

2016-01-22_14h34_50

2016-01-22_14h36_03

Wenn ich jetzt eine Datei will, wo ur noch alle Pakete mit xeq und err drin sind, habe ich verschiedene Möglichkeiten.

Anders sieht es aus,w enn man die REihenfolge der Dateien änert. Hierzu habe ich einfach mal testweise die REihenfolge der modifzierten Datei geändert, indem ich eine STelle ausgeschnitten und am Ende der DAtei eingefügt habe

T /AIF/BDC_IF_CONF C err
D /AIF/BDC_IF_CONF I err
M /AIF/BDC_IF_CONF C xeq
P /AIF/BDC_IF_CONF~0 C xeq
U /AIF/BDC_IF_CONF C xeq
T /AIF/BDC_IF_GEN C xeq
D /AIF/BDC_IF_GEN I err
M /AIF/BDC_IF_GEN C err
P /AIF/BDC_IF_GEN~0 C err
U /AIF/BDC_IF_GEN C err
T /AIF/BDC_ST_CONF C xeq
D /AIF/BDC_ST_CONF I xeq

P /AIF/DOCUT~0 C err
U /AIF/DOCUT C err
T /AIF/DOCU_TAB C err
D /AIF/DOCU_TAB I err
M /AIF/DOCU_TAB C err
P /AIF/DOCU_TAB~0 C xeq
U /AIF/DOCU_TAB C xeq
T /AIF/DOCU_TABT C xeq
D /AIF/DOCU_TABT I xeq
M /AIF/DOCU_TABT C xeq
P /AIF/DOCU_TABT~0 C xeq
U /AIF/DOCU_TABT C err
T /AIF/ERR_APP C err
D /AIF/ERR_APP I err
M /AIF/ERR_APP C err
P /AIF/ERR_APP~0 C err
U /AIF/ERR_APP C err
T /AIF/ERR_INF C err
D /AIF/ERR_INF I xeq
M /AIF/ERR_INF C xeq
P /AIF/ERR_INF~0 C xeq
U /AIF/ERR_INF C xeq
T /AIF/LOGSYST C xeq
D /AIF/LOGSYST I err
M /AIF/LOGSYST C err
P /AIF/LOGSYST~0 C err
U /AIF/LOGSYST C err
T /AIF/NEWDEVPROJS C err
D /AIF/NEWDEVPROJS I err
M /AIF/NEWDEVPROJS C err
P /AIF/NEWDEVPROJS~0 C err
U /AIF/NEWDEVPROJS C xeq
T /AIF/NEWDEVPROJT C xeq
D /AIF/NEWDEVPROJT I xeq
M /AIF/NEWDEVPROJT C xeq
P /AIF/NEWDEVPROJT~0 C xeq
U /AIF/NEWDEVPROJT C xeq
T /AIF/NEWDEV_IDS C err
D /AIF/NEWDEV_IDS I err
M /AIF/NEWDEV_IDS C err
P /AIF/NEWDEV_IDS~0 C err
U /AIF/NEWDEV_IDS C ok
T /AIF/NEWDEV_IDST C ok
D /AIF/NEWDEV_IDST I ok
M /AIF/NEWDEV_IDST C ok
P /AIF/NEWDEV_IDST~0 C ok
U /AIF/NEWDEV_IDST C err
T /AIF/PERS_RP_MSG C err
M /AIF/PERS_RP_MSG C xeq
P /AIF/PERS_RP_MSG~0 C xeq
U /AIF/PERS_RP_MSG C ok
T /AIF/PERS_RTCFGR C ok
D /AIF/PERS_RTCFGR I ok
M /AIF/PERS_RTCFGR C ok
P /AIF/PERS_RTCFGR~0 C ok
U /AIF/PERS_RTCFGR C xeq
T /AIF/PERS_RTCFGT C xeq
D /AIF/PERS_RTCFGT I xeq
M /AIF/PERS_RTCFGT C xeq
P /AIF/PERS_RTCFGT~0 C ok
U /AIF/PERS_RTCFGT C ok
T /AIF/POC_C_CFGAD C ok

M /AIF/BDC_ST_CONF C xeq
P /AIF/BDC_ST_CONF~0 C xeq
U /AIF/BDC_ST_CONF C err
T /AIF/BDC_ST_GEN C err
D /AIF/BDC_ST_GEN I err
M /AIF/BDC_ST_GEN C err
P /AIF/BDC_ST_GEN~0 C err
U /AIF/BDC_ST_GEN C xeq
T /AIF/CIFPP_SS_AS C xeq
D /AIF/CIFPP_SS_AS I xeq
M /AIF/CIFPP_SS_AS C xeq
P /AIF/CIFPP_SS_AS~0 C err
U /AIF/CIFPP_SS_AS C err
T /AIF/CIFPP_TJSEL C err
D /AIF/CIFPP_TJSEL I err
M /AIF/CIFPP_TJSEL C err
P /AIF/CIFPP_TJSEL~0 C err
U /AIF/CIFPP_TJSEL C xeq
T /AIF/DOCU C xeq
D /AIF/DOCU I xeq
M /AIF/DOCU C xeq
P /AIF/DOCU~0 C xeq
U /AIF/DOCU C xeq
T /AIF/DOCUT C err
D /AIF/DOCUT I err
M /AIF/DOCUT C err

WinMerge erkennt dann zumindest die Zeilen, die keine Entsprechung zueinander haben. DAs heißt in der einen DAtei wird der Bereich als fehlend (grau) und in der anderen dann jeweils als vorhanden (gelb) markiert. Das manuell mit logischem Denken zu verknüpfen funktioniert bei so einem einfachen Beispiel, wo ich nur eine Abschnitt ausgeshcnitten und am Ende eingefügt habe, noch.

2016-01-23_00h13_20

komplizierter wird es dann schon, wenn in einer der beiden Dateien bestimmte Teile fehlen, also wenn beispielsweise eineige Pakete, die den STatus xeq haben und noch abgearbeitet werden müssen, es nicht in die zweite Datei schaffen, aus welchem Grund auch immer. Acuh diese Sektionen markiert dann zwar WinMErge als grau, und somit lässt sich wieder feststellen, welche Berieche fehlen, aber der Endpunkt ist spätestens dann ereicht, wenn einige Einträge in der zweiten DAtei dann auch och doppelt vorkommen.

T /AIF/BDC_IF_CONF C err
D /AIF/BDC_IF_CONF I err
M /AIF/BDC_IF_CONF C xeq
P /AIF/BDC_IF_CONF~0 C xeq
U /AIF/BDC_IF_CONF C xeq
T /AIF/BDC_IF_GEN C xeq
D /AIF/BDC_IF_GEN I err
M /AIF/BDC_IF_GEN C err
P /AIF/BDC_IF_GEN~0 C err
U /AIF/BDC_IF_GEN C err
T /AIF/BDC_ST_CONF C xeq
D /AIF/BDC_ST_CONF I xeq

P /AIF/DOCUT~0 C err
U /AIF/DOCUT C err
T /AIF/DOCU_TAB C err
D /AIF/DOCU_TAB I err
M /AIF/DOCU_TAB C err
P /AIF/DOCU_TAB~0 C xeq
P /AIF/DOCU_TAB~0 C xeq
U /AIF/DOCU_TAB C xeq
T /AIF/DOCU_TABT C xeq
D /AIF/DOCU_TABT I xeq
M /AIF/DOCU_TABT C xeq
P /AIF/DOCU_TABT~0 C xeq
U /AIF/DOCU_TABT C err
T /AIF/ERR_APP C err
D /AIF/ERR_APP I err
M /AIF/ERR_APP C err
P /AIF/ERR_APP~0 C err
U /AIF/ERR_APP C err
T /AIF/ERR_INF C err
D /AIF/ERR_INF I xeq
M /AIF/ERR_INF C xeq
P /AIF/ERR_INF~0 C xeq
U /AIF/ERR_INF C xeq
T /AIF/LOGSYST C xeq
D /AIF/LOGSYST I err
M /AIF/LOGSYST C err
P /AIF/LOGSYST~0 C err
U /AIF/LOGSYST C err
T /AIF/NEWDEVPROJS C err
D /AIF/NEWDEVPROJS I err
M /AIF/NEWDEVPROJS C err
P /AIF/NEWDEVPROJS~0 C err
U /AIF/NEWDEVPROJS C xeq
T /AIF/NEWDEVPROJT C xeq
P /AIF/DOCU_TAB~0 C xeq
D /AIF/NEWDEVPROJT I xeq
M /AIF/NEWDEVPROJT C xeq
P /AIF/NEWDEVPROJT~0 C xeq
U /AIF/NEWDEVPROJT C xeq
T /AIF/NEWDEV_IDS C err
D /AIF/NEWDEV_IDS I err
M /AIF/NEWDEV_IDS C err
P /AIF/NEWDEV_IDS~0 C err
U /AIF/NEWDEV_IDS C ok
T /AIF/NEWDEV_IDST C ok
D /AIF/NEWDEV_IDST I ok
M /AIF/NEWDEV_IDST C ok
P /AIF/NEWDEV_IDST~0 C ok
P /AIF/DOCU_TAB~0 C xeq
U /AIF/NEWDEV_IDST C err
T /AIF/PERS_RP_MSG C err
M /AIF/PERS_RP_MSG C xeq
P /AIF/PERS_RP_MSG~0 C xeq
U /AIF/PERS_RP_MSG C ok
T /AIF/PERS_RTCFGR C ok
D /AIF/PERS_RTCFGR I ok
M /AIF/PERS_RTCFGR C ok
P /AIF/PERS_RTCFGR~0 C ok
U /AIF/PERS_RTCFGR C xeq
T /AIF/PERS_RTCFGT C xeq
D /AIF/PERS_RTCFGT I xeq
M /AIF/PERS_RTCFGT C xeq
P /AIF/PERS_RTCFGT~0 C ok
U /AIF/PERS_RTCFGT C ok
T /AIF/POC_C_CFGAD C ok

M /AIF/BDC_ST_CONF C xeq
P /AIF/BDC_ST_CONF~0 C xeq
U /AIF/BDC_ST_CONF C err
T /AIF/BDC_ST_GEN C err
D /AIF/BDC_ST_GEN I err
P /AIF/DOCU_TAB~0 C xeq
M /AIF/BDC_ST_GEN C err
P /AIF/BDC_ST_GEN~0 C err
U /AIF/BDC_ST_GEN C xeq
T /AIF/CIFPP_SS_AS C xeq
D /AIF/CIFPP_SS_AS I xeq
M /AIF/CIFPP_SS_AS C xeq
P /AIF/CIFPP_SS_AS~0 C err
U /AIF/CIFPP_SS_AS C err
P /AIF/DOCU_TAB~0 C xeq
T /AIF/CIFPP_TJSEL C err
D /AIF/CIFPP_TJSEL I err
M /AIF/CIFPP_TJSEL C err
P /AIF/CIFPP_TJSEL~0 C err
U /AIF/CIFPP_TJSEL C xeq
T /AIF/DOCU C xeq
D /AIF/DOCU I xeq
M /AIF/DOCU C xeq
P /AIF/DOCU~0 C xeq
U /AIF/DOCU C xeq
T /AIF/DOCUT C err
D /AIF/DOCUT I err
M /AIF/DOCUT C err

Der Screenshot zeigt die Textdatei mit veränderter Reihenfolge und doppelten Einträgen. Zwar zeigt WinMErge hier mit grauen STellen an, dass an der gezeigten Stelle die Einträge auseinander gehen, liefert jedoch keine Aussage darüber, ob der Eintrag an anderer Stelle nochmal auftaucht oder sogar doppelt vorhanden ist. Diese informationen manuell herauszusuchen wäre ab einer bestimmten Komplexität nicht mehr zumutbar.

2016-01-23_00h13_20 2016-01-23_00h21_42

WAs muss man also machen? Nun wir müssen eine Methode finden, die Einträge in der Datei wieder so zu sortieren, dass sie wieder in der selben Reihenfolge dargestellt werden, und dann gegenüberstellen, ob ein Eintrag auf der einen Seite mindestens eine  Entsprechung auf der anderen Seite hat (oder mehrere bei doppelten Einträgen).

Eine Möglichkeit ist es, die beiden Dateien in Microsoft Excel einzufügen und wie im Projekt weiter oben beschrieben über ein Trennzeichen (in unserem Fall sind das Leerzeichen) in Spalten aufzuteilen.

2016-01-22_15h36_03

2016-01-23_00h25_04

Das ganze machen wir zweimal, also für beide Dateien, so dass die ersten vier Spateln A-D von der linken Datei und die Spalten G-J von der rechtne Datei eingenommen werden.

2016-01-23_00h26_19

Jetzt markieren wir die zusammengehörigen Saptlen der ersten Datei und wählen im Kontextmenü erstmal Zellen einfügen und dann Ganze Zeile. So schieben wir die inhatle um eine Zeile nach unten, damit wir eine Überschrit einfügen können, um ausienander halten zukönnen, welche Datei welche ist.

2016-01-23_00h27_11

2016-01-23_00h27_572016-01-23_00h29_06

Paketnamen, die nun in einer Datei doppelt vorkommen, können wir nun entfernen, in dem wir in der Registerkarte Daten das Icon Duplikate entfernen wählen.

2016-01-23_00h47_33

Dor twählen wir dann die Saptlen, die zu einer Datei gehören, also beispielsweise A-D, und dann die Spalte, anhand  derer Dupliakte erkannt und entfernt werden sollen, also z. B. B. Bie der anderen Datei amchen wir dann das gleiche. Wir wählen die Saptlen G-J und wählen als Erkennungsmerkaml die Spalte H aus.

Jetzt wollen wir noch die Reihenfolge der Dateien wieder in den Griff kriegen. DAzu klciekn wir links die vier Saptlen der ersten Datei n und klicekn dann in der registerkarte Start auf den Button Sortierne und FilternBenutzerdefinierte Sortierung und dann Sortieren nach: Spalte B. Ihr wedet merken, dass die benachbarten Spalten mitgezogen werden, die rechte Ausgangsdatei aber nicht gleich mitsortiert wird, weil wir zwei Saptlen abstand gelassen haben, so soll es sein.

2016-01-23_00h42_49

Diesen Vorgang wiederholen wir dann auch für die zweite Datei und sortieren auch diese. Nun sind alle Paketnamen in beiden Dateien in der selben Reihenfolge sortiert, egal wo sie ursprünglich in der Datei gestanden sind.

2016-01-23_00h34_30

Jetzt können wir ganz einfach über eine Wenn-Formel feststellen, ob eine Zeile in beiden Dateien vorhanden ist, oder nicht. Die Formel wäre beispielsweise

=WENN(B1=H1;"gleich";"fehlt")

Als Ergebnsi in der ersten Zeile erahtlen wir „gleich“. Durch einen Doppeklick auf das kleine Vierekc in der rechten unteren Ecke machen wir den Vergleich für alle Zeilen. Somit kriegt man gnaz einfach raus, welche Zeilen gleich sind und welche nicht.

2016-01-23_00h40_06

Eine ander eMöglichkeit wäre es, die Spalten B und H zu markieren und dann im Reiter Start – Bedingte Formatierung – Reglen zum Hervorheben von Zellen – Doppelte Werte zu wählen. Somit wird gnaz einfach über eine Farbkodierung gezeigt, welche Einträge doppelt vorhanden sind und welche nicht – das funktioniert dann sogar ohne Sortierung, das heißt das Sortieren der Spalten hätten wir uns in diesem Schritt sparen können. Der Screenshot zeigt, dass die bedingte Formatierung den einen Wert zu wenig, den ich in der Ausgangsdatei gelassen und in der mit err/ok-belasteten Datei gelöscht habe, erkannt hat.

2016-01-23_00h56_59

Texteditor-Makros aufzeichnen mit Notepad++

Manche Textaufgaben sind einfach zu kompliziert, um sie mit KOmmandozeilentools oder manuell über einen TExteditor auszuführen. Für solche Afugaben gibt es Makros, die man mit einem TExteditor wie Notepad++ aufzeichnen kann. Ich spare mir hier umschweifende Beschreibungen und füge euch ein Youtube-Video ein, welches das Aufzeichnen und Verwenden eines Makros erklärt.

 

Andreas Loibl ist SAP-Berater, Ethical Hacker und Online Marketing Manager und schreibt auf seinem Blog DaFRK Blog über verschiedene Themen in den Sektoren Projektmanagement, Informationstechnik, Persönlichkeitsentwicklung, Finanzen und Zeitmanagement.

DaFRK

Andreas Loibl ist SAP-Berater, Ethical Hacker und Online Marketing Manager und schreibt auf seinem Blog DaFRK Blog über verschiedene Themen in den Sektoren Projektmanagement, Informationstechnik, Persönlichkeitsentwicklung, Finanzen und Zeitmanagement.

Das könnte Dich auch interessieren …

Kommentar verfassen

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.