PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Dateien mit Shell-Skript bearbeiten?



nobody0
23-04-2004, 21:14
Weil ich u. a. ein Skript zur Installation eines Crosscompilers ausbauen will suche ich noch eine Möglichkeit Dateien wie ~/.profile anzupassen, also z. B. sowas einzutragen:

PATH=$PATH:/usr/local/msp430/bin

aber wie bekommt man so etwas richtig hin, also nicht nur Anhängen sondern a) nur eintragen falls nicht vorhanden und b) einen vorhandenen Eintrag durch den neuen ersetzen? :confused:

Hans-Georg Normann
23-04-2004, 22:25
Wenn sichergestellt ist, dass PATH nur in einer Zeile definiert ist, dann dann man das schon mit sed hinbekommen.

Ist PATH kein bis mehrmals vorhanden, wird es schon komplizierter. Da würde ich auf den awk zurückgreifen. Damit geht's auf jeden Fall

Hans

peschmae
23-04-2004, 22:41
wenn die Ausgangslage ist:
Entweder kommt die Zeile so vor oder sie kommt nicht vor, dann würde ich das so machen:

1) Mit grep --quiet gucken ob die Zeile da ist (kannst die entsprechende eventuell ja auch mit einem speziellen Kommentar versehen auf den Grep anspricht)

2a) Wenn ja, sed s/vorher/nachher/ -i ~/.profile
2b) Wenn nein, echo nacher >> ~/.profile



ZEILE="PATH=$PATH:/usr/local/msp430/bin "
ZEILENEU="PATH=$PATH:/opt/msp431/bin"

if $(grep --quiet $ZEILE ~/.profile); then
sed s/$ZEILE/$ZEILENEU/ -i ~/.profile
else
echo $ZEILENEU >> ~/.profile
fi


Probleme dürfte wohl hauptsächlich das korrekte "Escapen" mit ", ' und \ der sed- und grep-Ausdrücke mit sich bringen.

MfG Peschmä

Hans-Georg Normann
23-04-2004, 23:02
ein echo >> ~/.profile könnte die Variable zu spät deklarieren, nämlich wenn sie exportiert wird und dann in einem weitern aufgerufenen Script benötigt wird.

@nobody0

Über wieviele Dateien reden wir hier eigentlich? Wie oft kommt das vor? Überleg einmal, ob folgendes Verfahren nicht schneller und sicherer ist.

Finde alle Dateien die zu ändern sind und schreibe sie mit samt Pfad in eine Datei. Dann vi $(cat dateiliste.txt) und der vi zeigt dir eine Datei nach der anderen an. Dann die Änderung vornehmen und :w! speichern und mit :n die nächste Datei aufrufen.

Es ist nicht der eleganteste Weg, aber unter Umständne hast du damit 100 Dateien schneller und sicherer bearbeitet als wenn du wilde shellscript Aktionen startest.

Hans

nobody0
23-04-2004, 23:44
Danke, dann werde ich mal die Lösung von peschmae nehmen :)

@Hans-Georg Normann: Automatisch ist besser ;)

peschmae
24-04-2004, 00:16
Original geschrieben von Hans-Georg Normann
ein echo >> ~/.profile[/B] könnte die Variable zu spät deklarieren, nämlich wenn sie exportiert wird und dann in einem weitern aufgerufenen Script benötigt wird.


Ok. Dann tun wir da halt noch ein export hin :)

MfG Peschmä

nobody0
24-04-2004, 17:37
Original geschrieben von peschmae


ZEILE="PATH=$PATH:/usr/local/msp430/bin "
ZEILENEU="PATH=$PATH:/opt/msp431/bin"

if $(grep --quiet $ZEILE ~/.profile); then
sed s/$ZEILE/$ZEILENEU/ -i ~/.profile
else
echo $ZEILENEU >> ~/.profile
fi



Damit gibt's das Problem, dass bei "PATH=$PATH:/usr/local/msp430/bin "
das $PATH expandiert wird. Wenn oben in der .profile $PATH geändert wird, dann wird es dadurch unten überschrieben und unwirksam.
Was kann man dagegen machen? :confused:

Das Problem habe ich nämlich auch mit


touch ~/.gdbinit
ZEILE="set remoteaddresssize 64"
ZEILENEU=$ZEILE
# ZEILENEU="PATH=$PATH:/opt/msp431/bin"
if $(grep --quiet $ZEILE ~/.gdbinit); then
sed s/$ZEILE/$ZEILENEU/ -i ~/.gdbinit
else
echo $ZEILENEU >> ~/.gdbinit
fi



denn das gibt:

grep: remoteaddresssize: No such file or directory
grep: 64: No such file or directory
grep: remotetimeout: No such file or directory
grep: 999999: No such file or directory
sed: -e expression #1, char 5: Unterminated `s' command

ThorstenS
24-04-2004, 17:42
Laß dir jede Variable mit echo $VARIABLE ausgeben, so debuggst du Stück für Stück
Setze ein sed in einer Version größer 4.0 ein, sonst ist der Schalter -i bzw. --in-file noch nicht implementiert.

nobody0
24-04-2004, 18:08
Ich verwende den
GNU sed version 4.0.6

peschmae
24-04-2004, 18:28
Eben, das Escapen. Tja.

1) Um zu verhindern dass eine Variable Expandiert wird machst du einfache Anführungszeichen drum: '
ZEILENEU='PATH=$PATH:/opt/msp431/bin'

2)
ZEILE="set remoteaddresssize 64"
if $(grep --quiet $ZEILE ~/.gdbinit); then

würde ich mal zu dem da abändern:
...
if $(grep --quiet "$ZEILE" ~/.gdbinit); then

mit " werden die variablen nämlich noch expandiert.

MfG Peschmä

P.S. die basteleien sind das was ich an Shell-Scripting am wenigsten mag :(

nobody0
24-04-2004, 19:21
Danke; das mit den einfachen Anführungszeichen wußte ich nicht mehr so genau :rolleyes:

Und die basteleien sind normal; 90 % der Zeit bei der Software-Entwicklung wird für's Debuggen benötigt.
Dafür wäre es schon hilfreich, wenn man eine Debug-Zeile hätte, mit der man die aktuelle Zeile ausgeben kann; da ist C viel weiter (mit __line_, __function__ usw.).

peschmae
24-04-2004, 19:34
Ja, aber das fällt für mich nicht unter Debuggen sonder unter nerven. Bash und Escapen ist irgendwie ein Kapitel wo manns nur falsch machen kann - und wenn dann noch Sed dazukommt...
Ich habe mal mehr als 3 Tage damit verbracht (natürlich nicht ausschliesslich aber die Grössenordnung ist schon erschreckend) herauszufinden, dass ich, selbst wenn ich eine sed-Regexp mit "" oder '' umschliesse, die runden Klammern separat mit \ escapen muss :rolleyes:

Für Bash gibts was in Richtung debugging - im Advanced Bash Scripting Guide hats ein Kapitel dazu - u.A. auch mit Link auf eine Debug-Bash-Shell. Habs aber so noch nie benutzt - hätte dir wohl im vorliegenden Fall auch nicht wirklich viel geholfen.

MfG Peschmä

nobody0
24-04-2004, 20:05
Und wieder das nächste Problem: Damit das Skript in ein konfigurierbares Verzeichnis installiert, verwende ich dafür eine Variable, aber durch die einfachen Anführungsstriche wird die nicht mehr interpretiert:

ZEILE='PATH=$PATH:$PREFIXROOT/bin'

Die Zeile muss also aus $PATH (nicht inertpr.) und $PREFIXROOT (interpretiert) zusammengesetzt werden. Wie bekommt man das mit der bash hin? :confused:

peschmae
25-04-2004, 08:09
ZEILE='PATH=$PATH:'"$PREFIXROOT/bin"

nach $PATH: kommt zuerst ein beendendes ' und dann ein anfangendes " :)

MfG Peschmä

nobody0
25-04-2004, 19:47
Aha, concatenation ist direkt möglich :)

Damit funktioniert es natürlich auch nicht:

sed: -e expression #1, char 25: Unknown option to `s'

Der sed mag diese Zeile nicht:

sed s/$ZEILE/$ZEILENEU/ -i $HOMEROOT/.gdbinit

Hier das Skript:



#!/bin/sh
export HOMEROOT=/home/$1
export PREFIXROOT=/usr/local/msp430
export PATH=$PREFIXROOT/bin:$PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib

if [ $# -ne 1 ]; then
echo "usage : $0 <user>"
echo "aborting"
exit -1
fi
echo "line 36"
# modify $HOMEROOT/.profile
touch $HOMEROOT/.profile
ZEILE='PATH=$PATH:'"$PREFIXROOT/bin"
ZEILENEU=$ZEILE
# ZEILENEU='PATH=$PATH:/opt/msp431/bin'
echo $HOMEROOT
echo $ZEILE
echo $ZEILENEU

if $(grep --quiet "$ZEILE" $HOMEROOT/.profile); then
sed s/$ZEILE/$ZEILENEU/ -i $HOMEROOT/.profile
else
echo $ZEILENEU >> $HOMEROOT/.profile
fi

echo "line 47"

# modify $HOMEROOT/.gdbinit
touch $HOMEROOT/.gdbinit
ZEILE='set remoteaddresssize 64'
ZEILENEU=$ZEILE
# ZEILENEU='PATH=$PATH:/opt/msp431/bin'
if $(grep --quiet "$ZEILE" $HOMEROOT/.gdbinit); then
sed s/$ZEILE/$ZEILENEU/ -i $HOMEROOT/.gdbinit
else
echo $ZEILENEU >> $HOMEROOT/.gdbinit
fi

echo "line 47"

ZEILE='set remotetimeout 999999'
ZEILENEU=$ZEILE
# ZEILENEU='PATH=$PATH:/opt/msp431/bin'
if $(grep --quiet "$ZEILE" $HOMEROOT/.gdbinit); then
sed s/$ZEILE/$ZEILENEU/ -i $HOMEROOT/.gdbinit
else
echo $ZEILENEU >> $HOMEROOT/.gdbinit
fi
ZEILE='target remote localhost:2000'
ZEILENEU=$ZEILE
# ZEILENEU='PATH=$PATH:/opt/msp431/bin'
if $(grep --quiet "$ZEILE" $HOMEROOT/.gdbinit); then
sed s/$ZEILE/$ZEILENEU/ -i $HOMEROOT/.gdbinit
else
echo $ZEILENEU >> $HOMEROOT/.gdbinit
fi

#
# We should be OK to go
#
echo ""
echo ""
echo "It appears we completed with no errors. MSP430 version of GCC is"


Ausgabe:

line 36
/home/rf0
PATH=$PATH:/usr/local/msp430/bin
PATH=$PATH:/usr/local/msp430/bin
sed: -e expression #1, char 19: Unknown option to `s'
line 47
sed: -e expression #1, char 5: Unterminated `s' command
line 47
sed: -e expression #1, char 5: Unterminated `s' command


It appears we completed with no errors. MSP430 version of GCC is

Irgendwelche Vorschläge? :confused:

peschmae
26-04-2004, 11:28
sed s/$ZEILE/$ZEILENEU/

geht nicht. Weil hier die Shell das draus macht:
sed s/PATH=$PATH:/usr/local/msp430/bin/PATH=$PATH:/usr/local/msp430/bin/
oder so ähnlich.

Benutze mal # statt / als sed-Superzeichen:
sed s#$ZEILE#$ZEILENEU#

und dann brauchts wohl hier auch noch Anführungszeichen (Schaden werden sie wohl nicht)
sed s#"$ZEILE"#"$ZEILENEU"#

MfG Peschmä

nobody0
26-04-2004, 23:23
Ja, das funktioniert nun, danke :)