ThomasR: Bitte um Hilfe zu AWK!

Liebe Community!

Ich gebe gleich zu, ich bin blutiger Anfänger im Scripting und AWK! Deshalb bitte ich um Nachsicht bei folgendem Problem! Beschreibung: Ich bin dabei mir ein Skript zu basteln, über welches ich diverse Informationen zusammen führe und optisch schön aufbereitet ausgeben will. Das mache ich im Moment per Ausleitung als HTML.

Nun habe ich ein Textfile(Beispiel.txt) das insgesamt aus 7 Zeilen besteht. Diese Zeilen bestehen aus Sätzen mit Informationen, die ich Zeile für Zeile und Spalte für Spalte verarbeiten will.

Beispiel:

Das ist Satz eins mit der zahl 50 und weiteren. Das ist Satz mit der 30 und weiteren. Das ist Satz drei mit 20 bis 30 Zahlen. Das ist Satz vier ....usw.

Nun hol ich mir in meinem Skript(Bash) per cut und awk die Info's und füge sie in die Tabelle ein, die dann wiederum auf dem html angezeigt wird. Das funktioniert eigentlich auch gar nicht so schlecht, allerdings komme ich einfach nicht auf die Lösung für mein folgendes Problem:

Ich möchte an einer Stelle eine zweizeilige Tabelle mit ebenfalls zwei Spalten. Ich kam schon drauf wie ich zwei Zeilen aus der Textdatei mittels awk separieren und übernehmen kann. allerdings erstellt mir awl immer automatisch zwei Tabellenzeilen, wohl weil ich ja auch zwei Zeilen aus der Textdatei übernommen habe. Nun möchte ich aber in der html Tabelle als Beispiel den Wert 50 in der ersten Tabellenzeile haben und aus der dritten Textzeile den Wert 30 und 20! Ich kann ja mit $8 die Spalte 8, also die 50, herausnehmen und verarbeiten. In der zweiten Zeile der html Tabelle fügt er mir aber auch die Daten von Zeile 1 der Textdatei ein. Da sollen aber die Daten aus der Textzeile 3 rein!

Wie spreche ich also über AWK die html tabelle so an, dass ich die Textdaten Zeile 1 in die Tabellenzeile 1 bekomme, und die Textdaten Zeile 3 in die Tabellenzeile 2?

Nochmal, bitte lacht euch nicht tot über meine Frage, aber egal wie viel ich auch schon gelesen habe zu AWK, ich bekomme es nicht hin. Mein Skript sind in dem Bereich im Moment so aus:

cat Beispiel.txt | awk ' NR == 1,NR==2 {print $0} ' | awk 'BEGIN{

            print "<TABLE border=3>" 
} 

{
		print "<TR>"
			
				{
					
				print "<td bgcolor=#00FFFF>&nbsp;Der Wert aus zeile 1 lautet&nbsp;&nbsp;&nbsp;&nbsp;</td>"
				print "<td bgcolor=#00FFFF>&nbsp;&nbsp;"$8"&nbsp;&nbsp;</td>"

				
				}
				
		print "</TR>"
		
		print "<TR>"
			
				{
					
				print "<td bgcolor=#00FFFF>Der Wert aus zeile 3 lautet</td>"
				print "<td bgcolor=#00FFFF>"$"</td>"
				
				}
				
		print "</TR>"

}
END{
		print "</TABLE>"
}' >>tester1.html
  1. Hallo,

    Ich gebe gleich zu, ich bin blutiger Anfänger im Scripting und AWK! Deshalb bitte ich um Nachsicht bei folgendem Problem!

    Ich weiß nicht, ob du mit deinem Problem hier richtig bist. AWK wird hier eher selten thematisiert.

    Nun habe ich ein Textfile(Beispiel.txt) das insgesamt aus 7 Zeilen besteht. Diese Zeilen bestehen aus Sätzen mit Informationen, die ich Zeile für Zeile und Spalte für Spalte verarbeiten will.

    Was denn nun? hast du eine Textdatei oder ein Tabellendokument?

    Ich kann ja mit $8 die Spalte 8, also die 50, herausnehmen und verarbeiten.

    Mit 8. Spalte meinst du also 8. Wort?

    Wie spreche ich also über AWK die html tabelle so an, dass ich die Textdaten Zeile 1 in die Tabellenzeile 1 bekomme, und die Textdaten Zeile 3 in die Tabellenzeile 2?

    Vermutlich musst du dich intensiver mit String-Verarbeitung mit AWK beschäftigen.

    In deinem Codebeispiel ist mir nur aufgefallen, dass du einmal $8 (für die 50) verwendest und einmal nur $. Das irritiert nicht nur mich, sondern vermutlich auch AWK.

    Gruß
    Kalk

    1. Hallo Kalk!

      Danke zunächst für die Antwort. Ich versuche es mal unabhängig von AWK zu formulieren und damit den Knoten, den ich bestimmt schon im Hirn habe, zu umgehen:-)

      Ich habe ein Textfile(beispiel.txt). Darin enthaltenen sind mehrere Zeilen(1-5).

      Ich möchte mir ein Skript(Shell/Bash) schreiben, welches mir eine Tabelle in einer html Datei erstellt. Die Tabelle soll zum Beispiel aus 2 Zeilen und 2 Spalten bestehen. Also so:

      <tr> <td><td/> </tr> <tr> <td></td> </tr>

      (abgekürzt dargestellt, Table und th etc. habe ich extra weggelassen) Jetzt möchte ich aber nicht alle 5 Zeilen aus der Datei beispiel.txt nehmen, sondern ich möchte

      Zeile 1 aus der beispiel.txt in die erste Zeile der Tabelle

      und

      Zeile 3 aus der beispiel.txt in die zweite Zeile der Tabelle schreiben!

      Wie also ordne ich der ersten Zeile der Tabelle die erste Zeile des beispiel.txt zu und der zweiten Zeile der Tabelle die dritte Zeile von beispiel.txt. Ich kann natürlich die beiden Zeilen separiert ausgeben, dann fügt mir das Skript automatisch die Zeilen untereinander ein. Ich möchte aber vielleicht das erste Feld von Zeile 2 der Tabelle individuell beschriften und nur im zweiten Feld von Zeile 2, einen kleinen Teil von Satz drei aus beispiel.txt übernehmen.

      Ich hoffe damit kannst du was anfangen?! Vielleicht ist die Lösung so offensichtlich, dass ich sie einfach nicht mehr erkenne(wie gesagt, Knoten im Hirn)!

      danke schon mal für deine Hilfe!

      Gruß Tom

      1. Hallo,

        Ich hoffe damit kannst du was anfangen?!

        Nein, denn das was du jetzt nochmal erläutert hast, war vorher schon klar.

        Nicht klar ist, wie man in AWK mit Zeichenketten aka Strings arbeitet. Das ist jetzt deine Aufgabe, das zu recherchieren. Es gibt sicherlich im Netz Tutorials, die das thematisieren.

        Gruß
        Kalk

    2. Ich weiß nicht, ob du mit deinem Problem hier richtig bist. AWK wird hier eher selten thematisiert.

      Zumindest wenn zumindest ich Zeit habe ist er hier richtig.

  2. Wie spreche ich also über AWK die html tabelle so an, dass ich die Textdaten Zeile 1 in die Tabellenzeile 1 bekomme, und die Textdaten Zeile 3 in die Tabellenzeile 2?

    Erkenntnis:

    Du willst in AWK eine CSV-Datei auswerten und dabei die Reihenfolge der ausgegebenen Zeilen verändern.

    Frage:

    Ist dieser Wunsch rein willkürlich oder folgt dieser einem Schema - soll zum Beispiel die Ausgabe sortiert erfolgen? Dann würde ich nämlich ganz anders vorgehen:

    nl      - Nummeriert Zeilen des Inputs
    sort    - sortiert
    grep    - filtert Zeilen
    cut     - schneidet Spalten aus und baut neu zusammen
    

    sind hier Deine mächtigen und sehr schnellen Freunde.

    Ein Hinweis:

    <td bgcolor=#00FFFF>Der Wert aus zeile 3 lautet</td>"`
    

    Du zeigst uns HTML aus dem vorigen Jahrtausend. Das ist inzwischen verpönt.

    Noch ein Hinweis:

    Das mit dem AWK zu HTML-Tabellen verwende ich zwar als Beispiel für die Nutzung des AWK - aber im realen Leben ist diese Idee eher „dritte Wahl“… Klüger ist es eine andere Programmiersprache zu verwenden - für diese Sache wären PHP ein Kandidat.

    Zur Sache:

    cat Beispiel.txt | awk ' NR == 1,NR==2 {print $0} ' | awk 'BEGIN{

    (das funktioniert eh nicht!)

    Du kannst den awk-Skript-Teil in einer eigenen Datei unterbringen, e.g, skript.awk.

    Dann startest Du die Abarbeitung ganz einfach mit

    awk -F ' ' -f skript.awk < Beispiel.txt
    

    Allgmein zum AWK:

    Der AWK unterscheidet 3 Abschnitte:

    BEGIN {
        # Was hier steht wird ausgeführt, bevor der AWK die erste Zeile der Daten abarbeitet.
    }
    
    {
       # Was hier steht wird für jede Zeile der Datendatei ausgeführt.
    }
    
    END {
       # Was hier steht wird ausgeführt, nachdem der AWK alle Zeilen der Datendatei abgearbeitet hat.
    }
    

    RTFM

    man 1 awk hilft Dir weiter, da stehen sogar Beispiele drin. Auch die oben genannten Befehle haben ein Manual:

    man 1 befehl oder die Kurzhilfe mit befehl --help helfen Dir weiter.

    1. nl      - Nummeriert Zeilen des Inputs
      sort    - sortiert
      grep    - filtert Zeilen
      cut     - schneidet Spalten aus und baut neu zusammen
      

      Da wären dann noch

      head -n2     - liefert die obersten 2 Zeilen
      tail -n2     - liefert die untersten 2 Zeilen
      

      head --help bzw. tail --help - hier sollte die Kurzhilfe reichen …

  3. Was für ein Spaßrätsel. Dann räumen wir mal mit der sehr verwirrend formulierten Aufgabe auf und ergänzen das Zeug...

    Wir haben also eine Input-Datei, von der willkürlich (und semantisch grob-falsch!) die erste und dritte Zeile in einer HTML-Tabelle ausgegeben werden soll. Das ist ziemlich merkwürdig und ich bin etwas „gnaaaazig“, weil @ThomasR auf meine Rückfrage nicht reagiert - aber es sei so...

    Ich entwerfe eine Input-Datei namens "daten.txt":

    Erster Satz.
    Zweiter Satz.
    Dritter Satz.
    Vierter Satz.
    Fünfter Satz.
    Sechster Satz.
    Siebenter Satz.
    

    Da Tabulatoren in der HTML-Ausgabe keine andere Bedeutung haben und von uns selbst als Trenner gebraucht werden ersetzen wir diese durch Leerzeichen:

    ~> tr "\t" " " < daten.txt
    

    Um feststellen zu können, welches denn die erste und dritte Zeile sei, nummerieren wir die einfach mal so durch, dass die Zeilennnummer am Anfang steht. Das dann so, dass leere Zeilen gar nicht erst nummeriert werden:

    ~> tr "\t" " " < daten.txt | nl -b t -n ln 
    1     	Erster Satz.
    2     	Zweiter Satz.
    3     	Dritter Satz.
    4     	Vierter Satz.
    5     	Fünfter Satz.
    6     	Sechster Satz.
    7     	Siebenter Satz.
    

    Das sieht gut aus. Also filtern wir mit grep nach der ersten und dritten Zeile

    ~> tr "\t" " " < daten.txt | nl -b t -n ln  | grep -E '^1 |^3 '
    1     	Erster Satz.
    3     	Dritter Satz.
    

    und geben also wie folgt aus: erste Spalte mit den Nummern, dann ein Tabulator (mehrere Leerzeichen werden so auch erkannt), dann zweite Spalte mit dem eigentlichen Inhalt. Damit lässt sich dann im AWK schon mal arbeiten.

    Wir notieren als Datei "daten.awk":

    BEGIN {
      FS="\t"; 
    	print "<table>";
    }
    
    
    {
        print "    <tr>";
        print "        <td>Zeile: "$1*1"</td>";
        print "        <td>"$2"</td>";
        print "    </tr>";	
    }
    
    END {
    	print "</table>";
    }
    

    und probieren das mal aus:

    ~> tr "\t" " " < daten.txt | nl -b t -n ln  | grep -E '^1 |^3 ' | awk -f daten.awk 
    <table>
        <tr>
            <td>Zeile: 1</td>
            <td>Erster Satz.</td>
        </tr>
        <tr>
            <td>Zeile: 3</td>
            <td>Dritter Satz.</td>
        </tr>
    </table>
    

    Das sieht Deiner Anfprdrung schon mal sehr ähnlich. Die Formatierungen im asbach-alten HTML 2.0 kannst Du gerne selbst ergänzen. Aber mit

    ~> tr "\t" " " < daten.txt | nl -b t -n ln  | grep -E '^1 |^3 ' | sort -k1 -n -r | awk -f daten.awk
    <table>
        <tr>
            <td>Zeile: 3</td>
            <td>Dritter Satz.</td>
        </tr>
        <tr>
            <td>Zeile: 1</td>
            <td>Erster Satz.</td>
        </tr>
    </table>
    

    kann man die Ausgaben gerne auch umgedreht erhalten - nur falls sich irgendjemand fragt, warum ich denn wohl bittschön einen Blick auf sort empfohlen habe…

    1. Auch wenn es nur Spaß ist: Da fehlt doch noch was...

      Falls in der Textdatei daten.txt HTML vorkommen könnte sollten wir uns noch sed ansehen:

      echo '<h1>Hallo</h1>' | sed -e 's/</\&lt;/g' -e 's/>/\&gt;/g'
      &lt;h1&gt;Hallo&lt;/h1&gt;
      

      Das bauen wir brav ein:

      ~> tr "\t" " " < daten.txt | sed -e 's/</\&lt;/g' -e 's/>/\&gt;/g' | nl -b t -n ln  | grep -E '^1 |^3 ' | awk -f daten.awk