• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Einzelne Zeilen in Dateien ändern - Shell

Picco

Newbie
Hallo zusammen,

ich habe gerade meine Vorliebe für Shell-Scripte entdeckt.
Jetzt versuche einfach mal eine paar kleine Kopiervorgänge usw. in Scripte zu fassen. Das klappt soweit auch ganz gut.

Jetzt sitze ich hier und suche nach einer Lösung für folgendes Problem:

Bei allen Serverdiensten, die man einrichten kann muss man in Konfigurationsdateien schreiben. (bzw. Parameter ändern)
Jetzt suche nach einer Möglichkeit bestimmte Zeilen in einer Datei zu finden und in dieser Zeile Werte zu ändern. Oder evtl. auch Zeilen auszukommentieren.
Ich habe da schon einiges mit grep und cat ...etc versucht, es hat aber nichts so richtig zum Erfolg geführt.
Kann mir da einer von Euch vielleicht helfen.

Schönen Dank ...

Gruß

Picco
 

TeXpert

Guru
im Prinzip machst Du das so (Pseudocode)

Code:
lese Datei zeilenweise
   für aktuelle Zeile:
        wenn Bedingung erfüllt -> ersetze irgendeinen Text
        schreibe aktuelle Zeile (evtl. modifiziert) auf die AUsgabe

hier wird Bash aber schnell mühsam :) da würde ich auf awk oder perl zurückgreifen...
 
OP
P

Picco

Newbie
Hi,

danke für Deine Antwort ... also so in etwa habe ich mir dass auch gedacht, bzw. habe ich mir dass so auf einen Zettel geschrieben.
Der Punkt mit ... wenn Bedingung erfüllt setze einen Text bekomme ich auch hin, bzw. würde ich schlimmsten Falle einfach die ganze Zeile weglöschen und neu schreiben.
Dieses zeilenweise wandern und das Erkennen der entsprechenden Zeile macht mir Gedanken.
Ich vermute mal, dass ich da nicht um mein "Lieblingsthema" reguläre Ausdrücke herumkomme. :lol:
Hast Du (oder auch jemand anders) vielleicht eine Idee wie ich da weiter vorgehen kann ??
Wie kann ich zeileweise durch eine Datei gehen ... bzw. ... gibt das der grep-Befehl her ?
Ich werde hier auch noch mal probieren.

Schönen Dank schon mal

Picco
 

nbkr

Guru
Wie TeXpert schon sagte, nimm für sowas eine Scriptsprache. Perl, Awk, Python, was auch immer, aber mit der Shell bricht man sich da einen ab.
 

nobbiew

Hacker
Wenn du tatsächlich die Datei direkt ändern willst, hilft dir ein grep herzlich wenig, da du dann nicht erkennen in welcher Zeile du gerade bist.

Ich kann mich da nur meinen Vorrednern anschließen. Mit der Bash wird´s schwierig. Ich würde da meinen Liebling (perl) zum einsatz bringen:

Im prinzip geht das ganze dann etwa so:
Code:
#!/usr/bin/perl
use strict;

   open FILE, "$ARGV[0]" or die "$ARGV[0]:$!";
   my @text = <FILE>;
   close FILE;
   foreach my $line ( @text ) {
     if ( $line =~ /^(\s*PARAMTER)=.*/ ) {
       $line = "$1=NEUERWERT\n";
     }
   }
   open NEW, ">$ARGV[0].new" or die "$ARGV[0].new:$!";
   print NEW @text;
   close NEW;
 

TeXpert

Guru
nobbiew schrieb:
Ich kann mich da nur meinen Vorrednern anschließen. Mit der Bash wird´s schwierig. Ich würde da meinen Liebling (perl) zum einsatz bringen:

naja, es kommt immer drauf an ;) wenn es nur um kleine Ersetzungen geht dann passt das auch mit einem Shellscript,

jetzt mal im direkten Vergleich
Code:
#!/bin/bash
while read line
do
    echo "$line" >> "$1.new"    
done < $1

schreibt einfach zeile für Zeile rein, jetzt also z.B. genau einen ini-Fiele-Eintrag ändern,

Code:
echo "$line" | sed -e 's/^\(foobar=\).*$/\1neuerWert/' >> "1.new"

im Prinzip gebe ich Dir recht, dass für diese Aufgaben andere Tools idr geeigneter sind, aber bei trivialen problemen kommst Du auch mit Bash schnell zum Ziel.
 
A

Anonymous

Gast
Evtl. hilft dir das hier weiter, http://www.fernuni-hagen.de/urz/leseecke/B006.html

Stichwort sed und Reguläre Ausdrücke.
Finde ich jedenfalls noch schneller zu durchschauen als Perl von Grund auf zu erlernen.

robi
 

regexer

Advanced Hacker
Egal welche Scriptsprache: Man geht i.d.R. nach folgendem Prinzip vor:
1. Lese zu verändernde Datei zeilenweise
2. Für jede Zeile: Ändere und schreibe sie in neue Datei
3. Kopiere neue Datei auf zu verändernde Datei

In Perl gibt es noch eine andere Möglichkeit. Hier kann man mit dem Modul "Tie::File" arbeiten, und eine Datei sozusagen an ein Array "binden". Sicher findest du über google mehr darüber ...
 
OP
P

Picco

Newbie
Hallo,

erst mal schönen Dank für Eure regen Antworten.

Also "geperlt" habe ich schon mal, allerdings reichen meine Kenntnisse da nicht aus.... ich werde mich da aber in nächster Zeit auch noch mal draufstürzen.

Zur Zeit bin ich an die Shell gekettet... nebenbei bin ich immer wieder überrascht was die alles kann.

Ich habe z.B. schon mal mit dem grep gearbeitet und solche Sachen gemacht wie:

grep -v "\#" > datei

In diese Richtung habe ich jetzt weiterüberlegt...

...mal ein Beispiel ... ich würde z.B. gerne ein Script schreiben, dass mir die Groupware (OX) auf der SuSE 9.2 installiert, bzw. diese ganzen Kopiervorgänge und Überprüfungen der Einträge abnimmt.
(ich weis.... braucht man nicht wirklich, aber was man hat das hat man)
Hier gibt es die postgresql unter /etc/sysconfig.
Dort muss unter anderem ...
POSTGRES_OPTION="-i"
Code:
... gesetzt werden. 
Wie schon gesagt ... egal, ob ich die Zeile ganz neu mache oder auch nicht... das muss doch irgendwie mit der Shell gehen.
Glaubt mir ... wenn ich Zeit hätte mich weiter in Perl einzuarbeiten würde ich da tun.
Es muss doch gehen z.B. beim grep mit dem [b]^[/b] oder so eine bestimmt Zeile zu finden. 

Ich habe das Gefühl, dass ich da ganz dicht dran bin....

Schönen Dank für  Euer Hirnschmalz

Gruß

Picco

P.S.: Danke roby für den Link werde ich mir jetzt mal genauer anschauen.
 
A

Anonymous

Gast
Was du da genau meinst ist schlecht rauslesen, da du hier scheinbar etwas mit den Textmakierungen durcheinander gekommen bist.
POSTGRES_OPTION="-i" und andere Variabelsetungen in irgendwelchen Konfigdateien, teste ich gelegentlich folgender Maßen

Subshell öffnen und darin mittels
Code:
 . ./KONFIGDATEI
die Konfigdatei einlesen und dann einfach testen ob deine Variable zB POSTGRES_OPTION jetzt den richtigen Wert in der Subshell hat.
Code:
 if [ $POSTGRES_OPTION = "-i" ]
Aber Vorsicht sollte man wirklich nur mit wirklichen Konfigdateien machen, sonst geht sowas schnell mal in die Hose.

robi
 
OP
P

Picco

Newbie
:lol: jau .... hab wohl ein "Code" nicht zu gemacht :roll: pfui .....

Also, erst mal danke für die Antworten.... was die Konfig-Dateien angeht .... da könnte ich zur Not natürlich auch einfach kopieren und dann die Rechte anpassen.
Aber wenn ich z.B. Einträge in Dateien pflegen muss,. z.B. Ldap-Parameter (zuhause.local oder firma.meine oder sowas), muss ich ja häufig Dateien nacheditieren.

Z.B. ... um mal beim OX zu bleiben ...

Der OX wird auf einem LDAP-Server installiert.
Die Schema-Datei wird in das entsprechende Verzeichnis kopiert.
Jetzt müsste doch auch noch der Eintrag in der slapd.conf gepflegt werden, bzw. die Schema-Datei dort eingetragen werden.
Ich habe mir am Wochenende noch mal die Man-Pages zum Grep durchgelesen.... irgentwie komme ich da auch nicht so recht weiter.
Selbst wenn ich die richtige Stelle finde, bekomme ich es nicht hin genau dort was reinzuschreiben.
Naja, ich sehe es schon kommen ... ich werde mich noch mal in Perl einarbeiten müssen.
:x
Vielleicht finde ich ja doch noch was ... das werde ich natürlich hier kund tun.

Schönen Dank Euch für Eure Hilfe ...

Gruß

Picco
 

TeXpert

Guru
Picco schrieb:
Ich habe mir am Wochenende noch mal die Man-Pages zum Grep durchgelesen.... irgentwie komme ich da auch nicht so recht weiter.
Selbst wenn ich die richtige Stelle finde, bekomme ich es nicht hin genau dort was reinzuschreiben.
Naja, ich sehe es schon kommen ... ich werde mich noch mal in Perl einarbeiten müssen.

grep allein hilft Dir auch nicht.... grep kann Dir nur in folgender Art und Weise helfen:

Code:
grep -n 'SUCHPATTERN' DATEI | cut -d: -f1
das liefert Dir dann die Zeile in der das Pattern steht.. editieren musst Du immer noch.

also 2 Varianten:

a/ mit Bash + sed oder Perl oder ...
Code:
für jede zeile in Datei tue
     wenn Zeile passt auf pattern -> editiere
     schreibe aktuelle Zeile in Zieldatei
ende_wenn

oder b/ bash + grep + cut + head + tail
Code:
ermittle Zeilennummer (das haben wir oben grep + cut)
kopiere die ersten n-1 Zeilen in die neue Datei
schreibe Zeile n
kopiere die letzten Zeilen von n+1 bis ende in die neue Datei
für die ersten und letzten nimmst Du Dir mal man head und man tail zur Brust.
 

nbkr

Guru
Das sich der OP trotz mehrmaligen Versuchen nicht zu einer Programmiersprache übereden lässt verschiebe ich das mal ins Konsolenforum. :wink:
 
sed mach glücklich...
Code:
prompt> cat dummy
ich bin
ein Text zum Ersetzen
# Kommentar

prompt> sed -i -e "/ein Text/s/ein Text/kein Text/" dummy
prompt> cat dummy
ich bin
kein Text zum Ersetzen
# Kommentar

syntax:
-i gleich ändern in der Datei
-e <pattern> Arbeitsstring angeben
pattern Beispiele, Das Format sieht aus wie:
/nurdiesezeilen/s(für ersetze)/was ersetzen/wodurch ersetzen/

Setzt "#" vor DUMMY am Anfang:
/DUMMY/s/^DUMMY/#DUMMY/

Ersetzt CONFIGPARM mit neuem Wert, Wert enthält "/"
/CONFIGPARM/s#.*#CONFIGPARM=/ich/nutze/slash#

Viele Grüße,

Haveaniceday
 

regexer

Advanced Hacker
haveaniceday schrieb:
syntax:
-i gleich ändern in der Datei
-e <pattern> Arbeitsstring angeben
pattern Beispiele, Das Format sieht aus wie:
/nurdiesezeilen/s(für ersetze)/was ersetzen/wodurch ersetzen/
Den -i kannte ich noch gar nicht. Den muss es aber auch erst seit kurzem geben, denn SLES 8 kennt diesen noch nicht.

Noch zwei Anmerkungen zum Thema "substitute":
1. Es ist nicht unbedingt notwendig, nach dem String zu suchen bevor man das kommando "s" abschickt. Dein Beispiel würde auch so funktionieren:
Code:
s/ein Text/kein Text/
2. Wenn alle Textstellen, in denen "ein Text" vorkommt ersetzt werden sollen, muss der Parameter "g" angegeben werden. Also:
Code:
s/ein Text/kein Text/g
 
OP
P

Picco

Newbie
@nbkr .... danke fürs Verschieben ... ich wusste selber nicht so genau wohin damit

@TeXpert : Dass der Grep alleine das nicht kann habe ich auch nicht erwartet. Das mit Cut und Tail ist das was mir da so vorgeschwebt ist.
Werde in der Richtung mal weiter ausprobieren.
Schönen Dank.

@haveaniceday: Das klingt ziemlich gut ... ich werden dass mal in einem meiner Scripte hier testen.
Schönen Dank

Gruß

Picco
 
Oben