Streameditor sed

sed ist ein Stromeditor (stream editor).
Ein Streameditor wird für grundlegende Texttransformationen auf einen Eingabestrom (einer Datei oder aus einer Verarbeitungskette) verwandt.
Obwohl in einigen Aspekten ähnlich zu einem Editor, der Bearbeitungen nach Skript erlaubt (wie Ed), führt Sed nur einen Durchlauf über die Eingabe(n) durch und ist somit effizienter. Allerdings ist es die Fähigkeit von Sed, Text in einer Verarbeitungskette zu filtern, die ihn besonders gegenüber anderen Arten von Editoren auszeichnet.


 sed [-V] [--version] [--help] [-n] [--quiet] [--silent]
           [-l N] [--line-length=N] [-u] [--unbuffered]
           [-E] [-r] [--regexp-extended]
           [-e Skript] [--expression=script]
           [-f Skriptdatei] [--file=Skriptdatei]
           [script-if-no-other-script]
           [Datei …]
           
           
 Eine komplete Übersicht des Kommandos finden Sie in den MAN-Pages  man sed 



Sie haben sich dem Sourcecode eine Programmauschnits anzeigen lassen und wollen den ine einem eigenen Programm weiter verarbeiten.
Leider wird der Soucecode als eine laaaaange Zeile angezeigt.
Mittels des sed können Sie die Datei jedoch an gewünschten Stellen umbrechen
Hier soll das nach </div> und nach </span> erfolgen.


sed -i 's/<\/div>/<\/div>\n/g' datei.text
sed -i 's/<\/span>/<\/span>\n/g' datei.text


sed: Der Text-Editor für das Terminal.

    -i: Ändert die Datei direkt (in-place).
    
    's/ALT/NEU/g': Ersetzt jedes Vorkommen 
    ALT durch NEU  
    \n: Steht für den Zeilenumbruch der an NEU angehängt wird.
    (global, g) wendet auf jedes Vorkommen an. 
    Als Trennzeichen wird häufig der / verwendet.
    Das macht das etwas unleserlich wenn ein / auch 
    Teil des   Ausdrucks ist. 
    In diesem Fall muss er im Ausduck mit \/ maskiert werden.
    Als Trennzeiche kann aber auch ein anders Zeichen 
    verwendet werden.
    Z.B. # oder | es sollte nur nicht im Ausdruck vorkommen.
    Weiter unten sehen Sie dazu ein Beispel,


Tipp für macOS:Nutzen Sie auf dem Mac einen leeren String nach -i,
da das dortige sed diesen zwingend benötigt:
sed -i '' 's/<\/div>/<\/div>\n/g' datei.text

Wenn man das häufiger benötigt kann man sehr gut in einem Bashscript ablegen.

Natürlich ist es immer probematisch, wenn eine Datei direkt geändert wird. Falls dabei etwas schiefgeht, steht man plötzlich ohne seine Daten da
sed hat dafür eine elegante Lösung: Die Erzeugung einer Backupdatei.

sed -ibak '' 's/<\/div>/<\/div>\n/g' datei.text

erzeugt eine datei.txtbak als Backupr
Achtung: wenn den Befehl mehrfach eingeben, um etwas auszuprobieren, wird die Datei immer wieder überschrieben und Sie stehen am Ende wieder ohne Daten da.

Es empfiehlt sich zunächst ohne den Parameter -i zu arbeiten.
Das Ergebnis wird dann auf dem Terminal ausgegeben oder si leiten die Ausgabe per Pipe in eine Datel um
sed  's/<\/div>/<\/div>\n/g' datei.text 

Wenn Sie nun wie oben vorgeschlagen nach 2 Kriterien suchen und diese ändern wollen, dann sollten wir unseren Aufruf ändern.
sed erlaubt uns mehrere scripte per -e an das Command zu übergeben.

sed  -e 's/<\/div>/<\/div>\n/g' -e 's/<\/span>/<\/span>\n/g' datei.text
 
 -e Skript, --expression=Skript
     Jeder expression beinhaltet ein script, das von sed abgearbeitet wird.
     In unserem Fall ein substitute  
     s/RegAusdr/Ersatz/
              Sucht die Entsprechung von RegAusdr im Musterbereich und 
              falls erfolgreich, ersetzt den passenden Teil mit Ersatz.  
             
 
   


Das liefert schon mal ein Ergebnis, aber es lässt sich noch optimieren : Alternative (bessere Lesbarkeit)
Wenn Sie statt des Schrägstrichs / ein anderes Trennzeichen wie das Pipe-Zeichen | (oder ein Rautezeichen #) für den s-Befehl nutzen, müssen Sie die HTML-Slashes nicht mehr mit Backslashes maskieren:
  sed -E 's#(</div>|</span>)#\1\n#g' datei.text 
  
  
  

-E: Aktiviert die erweiterten regulären Ausdrücke (ERE), 
  wodurch wir die runden Klammern und den Oder-Strich ohne Backslashes nutzen können.
  
  
  s#(</div>|</span>)# 
  		  Sucht entweder nach  </div> ODER nach </span> 
          und speichert den Treffer in einer nummerierten Gruppe.
          Auf die Gruppe kann bei der Änderung wieder
          zugegriffen werden.
          Der  Ersatz  kann  das  besondere  Zeichen & enthalten, um 
          auf den Teil des Musterbereichs zu verweisen, der 
          passte, und die besonderen Maskiersequenzen 
          \1 bis \9, die auf die entsprechenden passenden 
          Teilausdrücke  in  RegAusdr verweisen
 
 \1\n#    Fügt den gefundenen Text (Gruppe 1) wieder ein und setzt 
          den Zeilenumbruch (\n) direkt dahinter.
   
 g       global d.h. jeder gefundene Ausdruck wird ersetzt. 
  
  
   
 Ohne -i: Das Ergebnis wird direkt im Terminal ausgegeben,
  ohne die Originaldatei zu verändern.  
  Damit können wird erst einel unbesorgt testen und verschiedene
  Möglichkeiten ausprobieren, bevor wir das Ergebnis per
  
 sed -E 's#(<>/div>|</span>)#\1\n#g'  datei.text > ergebnis.txt
  
in eine andere Datei scheiben oder wir verwenden -i für "inPlace"

Weiteres Beispiel
sed  -i '/Herkunft: startup_1_0\.inc/!s/startup_1_0/startup/g'  startup.inc
 
Ersetzt alle Vorkommen die startup_1_0 enthalten aber nicht Teil von Herkunft: startup_1_0 sind durch startup
# SED



Diese Datei wurde von einem Programm erzeugt. Sie soll so umgewandelt werden, dass sie als JSON Tabelle verwendet werden kann.

```
2019.01.01|1||8:17.37|16:27.33| 8:09.55|12:29.27|  17.00°| -3.1
2019.01.02|2||8:17.07|16:28.08| 8:11.01|12:29.56|  17.09°| -3.5
2019.01.03|3||8:16.35|16:28.48| 8:12.12|12:30.25|  17.18°| -4.0
2019.01.04|4||8:16.01|16:29.30| 8:13.29|12:30.53|  17.28°| -4.5
2019.01.05|5||8:15.24|16:30.16| 8:14.51|12:31.21|  17.38°| -5.0
    :
2019.12.27|27||8:24.12|16:30.09| 8:05.57|12:26.59|  16.69°| -0.6
2019.12.28|28||8:24.24|16:30.57| 8:06.32|12:27.29|  16.74°| -1.1
2019.12.29|29||8:24.34|16:31.47| 8:07.13|12:27.59|  16.79°| -1.6
2019.12.30|30||8:24.40|16:32.41| 8:08.01|12:28.29|  16.85°| -2.1
2019.12.31|31||8:24.43|16:33.37| 8:08.54|12:28.58|  16.92°| -2.6
(END)
    
```

 

```
cat 2019_49.98081241_8.39973450.dat | sed -e 's/^\(.*\)$/"\1",/g'
```

Das Ergebnis   hat auch in der letzten Zeile noch ein , 

```
"2019.12.28|28||8:24.24|16:30.57| 8:06.32|12:27.29|  16.74°| -1.1",
"2019.12.29|29||8:24.34|16:31.47| 8:07.13|12:27.59|  16.79°| -1.6",
"2019.12.30|30||8:24.40|16:32.41| 8:08.01|12:28.29|  16.85°| -2.1",
"2019.12.31|31||8:24.43|16:33.37| 8:08.54|12:28.58|  16.92°| -2.6",
```



Um alles auf einmal zu erzeugen, wird mittele Pipe ein weiterer SED gestartet. Der zweite  SED fügt vor der ersten Zeile [   ein    und ersetzt das letzte  ,   durch einen Linefeed und  ]   und schreibt das Ergebnis in eine Datei

```
cat 2019_49.98081241_8.39973450.dat | sed -e 's/^\(.*\)$/"\1",/g' | 
                      sed -e '1 i\['  -e '$ s/\([0-9]"\),$/\1\n]/' > 2019_coords.json
```



Die Pipe kann aber auch noch weggelessen werden,  wenn alle e-Scripts in einem Kommando angegeben werden.

```
cat 2019_49.98081241_8.39973450.dat | 
   sed -e 's/^\(.*\)$/"\1",/g'  -e '1 i\['  -e '$ s/\([0-9]"\),$/\1\n]/' >  
   2019_coords_1.json
   
detlef@i7-dh:/data/../data$ head -3 2019_coords_1.json
[
"2019.01.01|1||8:17.37|16:27.33| 8:09.55|12:29.27|  17.00°| -3.1",
"2019.01.02|2||8:17.07|16:28.08| 8:11.01|12:29.56|  17.09°| -3.5",

detlef@i7-dh:/data/../data$ tail -3 2019_coords_1.json
"2019.12.30|30||8:24.40|16:32.41| 8:08.01|12:28.29|  16.85°| -2.1",
"2019.12.31|31||8:24.43|16:33.37| 8:08.54|12:28.58|  16.92°| -2.6"
]
detlef@i7-dh:/data/../data$ 

```





Diese Form  setzt auch noch hinter ]  ein ",

der regular Expression verwendet einen per \  maskierten Substring  \ (  \\)  der  mittels  .*   alle Zeichen der Zeile erfasst.

```
cat 2019_coords_rheim.dat | sed -e 's/^\(.*\)$/\1",/g'
```

Das geht jedoch einfacher mit :

```
cat 2019_coords_rheim.dat | sed -e 's/$/",/g
```





Hier wird davon ausgegangen, dass das letzte Zeichen jeweils eine Ziffer ist.

Damit wird nur beim letzten Eintrag noch ein überflüssigen , gesetzt. 

```
cat 2019_coords_rheim.dat | sed -e 's/\([0-9]\)$/\1",/g

"2019.12.31|31||8:24.43|16:33.37| 8:08.54|12:28.58|  16.92°| -2.6",
] 
```



------

In eienrm Webauftritt soll ermittelt werden, wo eine Zentrale Datei Termin und un Welcher Version verwendet wird. Die Ausgabe soll nach der Version aufsteigen in eine Datei zur weiteren Verarbeitung geschieben werden.

#/bin/bash


OUTFILE=/tmp/menu.txt
cd /data/htdocs

find   -P . -name "*.php"  -exec grep -H -n "new Menu_" {} \; |
 sed -e 's/^.*\(Menu.*[0-5]\).*$/\1:&/g'   | sort >   $OUTFILE


cat $OUTFILE | wc -l