[Shellskript] Doppelte Zeilen löschen

T

Tallatronic

Gast
Hallo Leute, ich bin der Talle und neu hier im Forum. Ich studiere derzeit online Medieninformatik in Brandenburg und wir beschäftigen uns im Betriebssysteme Kurs mit Shellskripten. Ich habe mich hier im Forum registriert um euch zu meinem shellskript zu befragen.

Die Aufgabe ist folgende:

"Schreiben Sie ein Shell-Skript, mit dem alle mehrfach hintereinander
vorkommenden Kommentarzeilen und Leerzeilen einer Datei durch
jeweils eine Leerzeile ersetzt werden. Das Shell-Skript soll sowohl auf
eine Datei wie auch für einen ganzen Baum angewandt werden können.
Die erzeugte neue Datei soll die Endung .red erhalten. Sofern ein
Verzeichnis angegeben wird, sollen selbstverständlich nur die darin
enthaltenen Textdateien umgewandelt werden. Ein Test, ob es sich um
Textdateien handelt muss vom Skript vorgenommen werden.
"

Mein Skript funktioniert auch grobgesehen wie beschrieben :)
Code:
#!/bin/bash


# Bildschirm wird geleert
clear


# Debugmodus aktiviert
set -x


# variable zeile0 wird fuer ersten Zeilenvergleich initialisiert
zeile0="MT"


# If-Schleife: 	(if) es wurde ein Parameter uebergebn und dieser ist entweder ein file oder directory
#		(elif) es wurde ein Parameter uebergeben, der weder file noch directory ist
#		(else) es wurde KEIN Parameter uebergeben

if [ $# != 0 ] && ([ -f $1 ] || [ -d $1 ]);
  then

# for-Schleife die alle Dateien im findet die auf Uebergabeparameter 1 zutreffen und die Endung .txt haben
        for i in `find $1 -name "*.txt"`
          do

	  # Counter wird mit 1 initialisiert

          n=1
          echo "Entferne alle doppelten Kommentarzeilen und Leerzeilen im Dokument: $i ..."
          sleep 2


		# while-Schleife welche die Datei(en) der for-schleife durchgeht und zeilenweise liest 
		# und in entsprechende Variablen (zeile1, zeile2, ...) speichert

                while read line
                  do
                  eval "zeile${n}=\"$line\""

			# if-Schleife welche die aktuelle Zeile mit der vorherigen vergleicht. Sind sie ungleich wird die Zeile in die 
			# Datei $1.red hinzugefuegt sind die Zeilen gleich, so wird eine Leerzeile in die .red Datei gehaengt

                        if ( cat text4.txt | grep '.*#' || [ -z "\$zeile$n" ]) && [ "$(eval echo "\$zeile$n")" = "$(eval echo "\$zeile`expr $n - 1`")" ]
                          then
			    echo "" >> ${i}.red
			  
 			  else
                            echo $line >> ${i}.red
                            n=`expr $n + 1`

                        fi

                  done <$i

          n=1
          echo "Ergebnis in ${i}.red gespeichert!"
	  echo ""
          done

  elif [ $# != 0 ]
    then
    echo "Der angegebene Parameter ist weder Datei noch Verzeichnis!"

  else
    echo "Es wurde kein Parameter angegeben!"

fi

Nun will ich aber nicht das mein "grep"-Kommando in Zeile 44 etwas ausspuckt also wollte ich "grep -q" verwenden aber das geht nicht. Im manual steht "-q" als "User Command", womit ich leider nichts anfangen kann. Meine Alternative Idee wäre den output auf dev/null umzuleiten, aber das finde ich etwas umständlich wenn es doch so ein tolles Kommando für grep gibt :rolleyes:

Das andere ist das ich eigentlich noch einen Hinweis schreiben wollte wenn es sich beim Übergabeparameter um eine Datei handelt, diese aber keine .txt ist. Kann ich das in der for-Schleife in Zeile 24 implementieren oder muss ich die if-Schleife am Anfang umbauen?

Und zu guter letzt, was sagt ihr zur effizienz des skripts? Ich weiß es ist wahrscheinlich tierisch umständlich geschrieben, mein programmierprof hat mir schon im ersten Semester gesagt das ich sehr "speziell" programmiere :)
Wo kann ich mir was einsparen?

Ich würde mich über eure Meinungen und Hilfestellungen sehr freuen!
Schöne Grüße,
Talle
 
@Kenterfie: das cat ist wie so oft komplett überflüssig.

Code:
uniq blah.txt

oder ev. besser, falls nicht sortierter text, und wirklich alle doppelten raus sollten

Code:
sort -u blah.txt

und wenn man das ganze in eine datei speichern will, einfach

Code:
sort -u blah.txt > blubb.txt

Edit: Sorry, überlesen. Du sollst nur bestimmte sachen filtrieren (leerzeilen/doppelte kommentare...). Das liesse sich ev. mit sed oder awk machen. Google mal nach sed duplicate lines

Und was das .txt oder nicht anbelangt, kannst du ja einfach testen ob's ein verzeichnis ist [ -d $x ], und falls ja, kannst ja mittels find $x -type f -name "*.txt" -print0 | xargs -0 dein-script ...
 
Zuletzt bearbeitet:
Hi und danke für die Antworten.
Leider habe ich etwas verpeilt. In Zeile 44 soll ja nicht:
Code:
 if cat text4.txt | grep '.*#'
stehen sondern es soll die aktuelle Zeile "gegrept" werden.

Also habe ich dort nun:
Code:
 if echo $line | grep '.*#'
da "uniq" nur auf dateien angewendet werden kann wie es scheint.
Ich habe nun erstmal die ausgabe von grep umgeleitet "> /dev/null".

Was "sed" angeht, da kenne ich mich kein bissl aus, was ich im Netz gefunden habe hörte sich auch nicht so an als ob ich es gebrauchen könnte. So gibt es Einzeiler die ALLE wiederholt vorkommenden Zeilen löschen, das ist hier aber nicht gefragt.

Ich werde das mal so rausschicken, denn... es funktioniert :) Auch wenns mir nicht sehr effizient vorkommt.

grüße,
Talle
 
Zurück
Oben