Fragen zur Textdateiverarbeitung

T

Tazzu

Hallo Leute ,

ich bin absoluter shell Neuling und muss mich nun wohl oder übel mit shell beschäftigen.

Mein Problem :
Wie lösche ich durch ein shell script die erste/letzte zeile einer textdatei ?
Und wie kann ich ein Attribut in eine textdatei schreiben und speichern ?

das ganze hat folgenden hintergund :

ich habe eine textdatei mit computernamen bei denen ich gewisse abfragen starte. in jeder zeile steht ein computername. ich schreibe die letze zeile in eine variable und starte gewisse abfragen. der output soll in eine textdatei geschrieben werden. danach soll die letze zeile gelöscht werden und das ganze geht von vorne los bis die datei leer ist ... kann mit wer ein bisschen syntax oder starthilfe geben ?

Danke Tazzu
 
Erste Zeile extrahieren:
Code:
head -n 1 myfile
Alles ausser letzter Zeile extrahieren:
Code:
head -n -1 myfile

Entsprechend mit tail fuer das Ende/ den Anfang, und wenn Du beide miteinander durch eine pipe verbindest, bist Du da, wo Du hinwillst.

Um eine Zeile zu erweitern, extrahierst Du die Zeile und gibst sie z.B. and awk weiter, womit Du dann die Zeile veraendern oder ihr etwas hinzufuegen kannst.
 
danke für deine antwort aber das auslesen einer bestimmten zeile ist nicht mein problem....

Nochmal :

Ich habe eine textdabei (computer.txt) in der die zu berarbeitenden computer ca so drinstehen :

computer1
computer2
...

ich will jetzt die letzte oder erste (ich nehme die letze mit tail -1) zeile nehmen und in eine var schreiben (so hab ich nur den computernamen in der variable) und anschließend mit dem namen arbeiten (frage ipadresse etc ab) . die ausgabe soll in eine neue datei geschrieben werden (ergebnisse.txt) und die letzte zeile in computer.txt gelöscht werden (damit ich computer die ich einmal abgefragt hab nicht nochmal abfrage)

meine schleife sieht ca so aus :

while [ "$N" != "" ] ;do
N=`cat /home/matthias/test.txt | tail -1`
echo $N

done

also holt er sich die letzte zeile bis es nichts mehr zu holen gibt. allerdings holt er sich ja momentan immer wieder den gleichen wert da die letzte zeile immer gleich bleibt.... meine Frage nun : wie lösche ich per befehl die letzte zeile einer textdatei?
 
Hallo Tazzu

Die letzte Zeile einer Datei kannst du z.B mit 'sed' löschen:
Code:
sed '$d'

Gruss
d22
 
versuchs mal mit sed & co.
Mit head kannst du die erste Zeile ausgeben lassen.
Mit cut glaube ich kannst du eine Zeile rausschneiden.
Einfach einmal rtfm machen.:)
 
Hallo
root1992 schrieb:
versuchs mal mit sed & co.
Mit head kannst du die erste Zeile ausgeben lassen.
Mit cut glaube ich kannst du eine Zeile rausschneiden.
Einfach einmal rtfm machen.:)

Mit all diesen Werkzeugen kannst du einen Datenstrom (Datei) gezielt auslesen.
Um ihn aber zu verändern und in wieder abzuspeichern, bedarf es dann noch entweder einer Pipe oder Umleitung oder einem Werkzeug, welches das direkt macht.
Der Ansatz mit sed '$d' ist da schon richtig.
Wenn du GNU sed hast, kannst du die Datei direkt editieren. -i
sed -i -e '$d' datei
oder wenn nicht GNU sed verfügbar ist:
sed -e '$d' datei >tempfile &&cat tempfile>datei && rm -f tempfile
Du könntest die Datei natürlich auch gleich komplett rückwärts zeilenweise ausgeben, in einer while read schleife abarbeiten, und am Ende komplett leeren.
Dazu gibt es z.B. tac
Code:
while read VAR; do
echo $VAR 
...
done < $(tac datei)
echo "All done"i
>datei
echo "file empty"
aber auch tac lässt sich mit sed simulieren: (ohne GNU sed)
sed -n -e 'G;h;$p' datei >tempfile
tempfile ist jetzt Zeilenweise umgedreht
mit GNU sed
sed -n -i -e 'G;h;$p' datei
datei ist nun umgedreht, erste Zeile ist letzte, und letzte nun erste Zeile. ;)
*das sollte man aber nur machen, wenn die Datei nicht riesig ist. Der Holsdspace hält nämlich dabei zwischenzeitlich die gesamte Datei!

Gruß Wolfgang
 
Moin,

es kann auch sein, dass ich mich täusche, aber ich vermute du willst die computer.txt Datei Schritt für Schritt leeren, nur weil du nicht weißt, dass es auch ohne Löschen einer Datei möglich ist eine Liste Zeile für Zeile abzuarbeiten - richtig oder falsch?

Wenn ja dann bietet dir Wolfgangs Ansatz bereits eine Lösung.
Wenn es nicht wichtig ist, dass die Datei von unten nach oben abgearbeitet wird (verstehe den Grund nicht ganz) - und was ich vermute, dann kannst du auch auf 'tac' verzichten und deine Schleife würde wie folgt aussehen (Mit Hilfe der Bash kannst du Dateien Zeilenweise auslesen und dementsprechend verarbeiten):
Code:
cat /home/matthias/test.txt | while read line; do
    echo $line;
done
Sollte ich mich irren und das sollte alles seinen Sinn und Zweck haben mit dem Leeren der Datei, dann vergiss mein Posting ;)
 
Ich hab da mal ne ähnliche Problemstellung, wo ich hier und woanders nicht ganz die gewünschte Lösung gefunden habe, daher schließe ich mich mal der Diskussion an :)

Ich habe eine Ausgabe auf der Shell, als Beispiel mal die des Befehls 'free'. Wie kann ich nun ohne überdimensionierte Umwege die erste Zeile weglassen? Dafür muss es doch eine effektive Lösung ohne großes Shell-Programming geben. Man könnte natürlich mit head 1 die erste Zeile extrahieren und dann per | grep -v die Zeile ausschließen, aber ich wollte mal wissen, ob es einen effektiveren Weg gibt.

Folgender oben genannte Tip funktioniert mit Tail leider nicht (alles ausser der 1. Zeile anzeigen lassen).

Da ich das relativ häufig verwende, wäre eine schnell arbeitende Lösung schön :)

rikola schrieb:
Erste Zeile extrahieren:
Code:
head -n 1 myfile
Alles ausser letzter Zeile extrahieren:
Code:
head -n -1 myfile

Entsprechend mit tail fuer das Ende/ den Anfang, und wenn Du beide miteinander durch eine pipe verbindest, bist Du da, wo Du hinwillst.

Um eine Zeile zu erweitern, extrahierst Du die Zeile und gibst sie z.B. and awk weiter, womit Du dann die Zeile veraendern oder ihr etwas hinzufuegen kannst.
 
Sowas?
Code:
free | awk '{getline; print}'
 
Schlaubi_fi.de schrieb:
Sowas?
Code:
free | awk '{getline; print}'

Danke, ich werd mir das mal genauer anschauen. Es macht leider nicht genau das, was ich will, da es jede zweite Zeile löscht, aber nun hab ich nen kleinen Hinweis, womit ich arbeiten kann :)
 
Hallo

Natürlich geht sowas über eine Pipe oder direkt mit den verschiedensten Werkzeugen:

Immer die erste Zeile aus Datei oder Datenstrom weglassen:
Mit sed (schneller als AWK, fällt aber kaum in's Gewicht)

Mit perl (langsamer als AWK)
free| perl -ne '(1..1)?1:print'

Man kann aber auch gezielt bestimmte Zeilen mittendrin weglassen, oder selektieren (alles ausser diesen Zeilen weglassen)
Angenommen Zeilen 2-4 aus einem Datenstrom (hier mal cat datei) ausgeben und den Rest weglassen:
mit sed
cat datei|sed -ne '2,4p'
Mit Perl:
cat datei|perl -ne '(2..4)?print:1'
Oder nur Zeilen 2 und 5 ausgeben
cat datei|perl -ne '(2..5)?(3..4)?1:print:1'

HTH
Gruß Wolfgang
 
Wow, danke, funktioniert super.
Ich hab versucht, das etwas nachzuvollziehen, jedoch kommt mir einiges immer noch recht kryptisch vor, wärst du so lieb, dein Vorgehen noch zu erläutern?

Code:
cat datei|perl -ne '(2..4)?print:1'
Soweit verstanden hab ich das: Hier z.B. macht die Option -e, dass Perl-Code direkt ausgeführt werden kann und -n scheint eine While-Schleife, die mit <> die Eingabe erwartet, also die Datei, um die Codezeile baut. Die Zeile an sich ist ne verkürzte if-else-Bedingung, jedoch ist mir nicht ganz klar, was an 2..4 die Bedinung ist. Klar bezieht sich das auf die Zeile, jedoch ist mir nicht klar, wie das realisiert wird.

Code:
cat datei|perl -ne '(2..5)?(3..4)?1:print:1'
Das ist dann noch verwirrender ;)

Code:
free|sed -e '1d'
Bei sed scheint die Option -e das gleiche zu bewirken. '1d' löscht dann die erste Zeile?

Code:
cat datei|sed -ne '2,4p'
Was macht hier dann das p?

Danke im Voraus!
 
(2..4) bezieht sich auf die Zeilennummer.

Code:
(2..5)?(3..4)?1:print:1
entspricht

Code:
if (2..5) {
  if (3..4) {
  } else {
    print
}

Die 1 ist nur ein Lückenbüßer und bewirkt nix. Sie ist nur für den korrekten Syntax von ?: nötig.

Gruss, Xanti
 
Zuletzt bearbeitet:
Zu dem sed:
cat datei|sed -ne '2,4p'

-n bewirkt, dass per default nix ausgegeben wird.
-e bewirkt, dass der nachfolgende Code direkt ausgeführt wird.
2,4 sind die Adressbereiche auf die sich nachfolgender Befehl bezieht
p ist der Printbefehl
Das Bewirkt also, dass nicht per default ausgegeben wird, und explizit nur die Zeilen 2 bis 4 mit ausgegeben wird.(p=print)
Ohne -n würden so die Zeilen 2 bis 4 doppelt ausgegeben.
Versuch es einfach mal.
Zu perl hat ja Xanti schon etwas gesagt.
Dem habe ich nix hinzuzufügen. ;)

Siehe auch:
perldoc perlrun
man sed
Sedtutorial eng.


Gruß Wolfgang
 

Ähnliche Themen

Keine grafische Oberfläche (Debian Installation)

Textformatierung nach Cut "\" nach jeder Zeile?

Doppelte Dateien löschen.

ersetzen in einem Rückgabestring eines vorher ausgeführten Programms

Logfile in Mysql?

Zurück
Oben