Archiv verlassen und diese Seite im Standarddesign anzeigen : suchen und ersetzen, Format erhalten
Bad_Rockk
07.07.2010, 10:04
Hallo zusammen,
beschäftige mich erst seit kurzem mit Programmierung und bin daher noch nicht so fit, also entschuldigt falls meine Frage eigentlich jedem anderen klar ist außer mir.
Arbeite mit cygwin.
Habe folgenden Code:
cat beispieltext.txt | sed -e "s/ x / y /g" > ergebnis.txtin der beispieltext.txt stehen 3 Zeilen:
Beispieltext
Ersetze x durch y
1 = 2
wenn ich jetzt das den Code ausführe, ersetzt er mit zwar mein x durch das y aber er löscht auch gleichzeitig die Zeilenumbrüche! Wie kann ich das verhindern? Die Datei soll danach eigentlich genauso aufgebaut sein wie zuvor nur mit den ersetzten Kriterien.
Habe jetzt gerade gesehen, dass wenn ich das ergebnis.txt in Notepad++ öffne, die Formatierung noch stimmt. Im normalen Windows Editor aber nicht. Besteht das Problem jetzt an meinem Code oder an Windows Editor?
edit:
Habe jetzt mal versucht zwei verschiedene Ersetzungen zu machen. Das ganze habe ich dann so gedacht, dass ich es universell einsetzen kann. Daher habe ich versucht mit Variablen zu arbeiten:
#bin/bash
#
DATEI="beispieltext.txt"
TEMP="temp.txt"
AUSGABE="ergebnis.txt"
#
SUCHE1=" x "
ERSETZE1=" y "
SUCHE2="1"
ERSETZE2="2"
#
cat $DATEI| sed -e "s/$SUCHE1/$ERSETZE2/g" > TEMP
cat $TEMP | sed -e "s/$SUCHE2/$ERSETZE2/g" > AUSGABE
Aber leider funktioniert das nicht so wie ich es gedacht habe. Bekomme die Fehlermeldung: No such File or Directory. Aber die Dateien sind da.
Als Ausgabe bekomme ich Dateien mit der Endung .txt] die aber leer sind?!
Das ganze ist nur ein erstes Beispiel für mich, damit ich die Funktionsweiße verstehe. Das ganze soll später in ein größeres Skript eingebaut werden. Dabei soll eine Datei mehrmals nach bestimmten Kriterien suchen und ersetzen, z.b. A mit Wert B aus Tabelle Spalte 1, C mit Wert D aus Tabelle Spalte 2 und E mit Wert F aus Tabelle Spalte 3 ersetzen. Und dann das ganze in einer Datei ablegen. Das ganze muss dann mehrmals gemacht werden, immer reihenweiße bis die Tabelle komplett abgearbeitet ist.
Aber das nur zu Info. Erstmal vorne Anfangen...
Würde mich freuen, wenn mir da jemand weiterhelfen könnte.
Gruß
Jan Krüger
11.07.2010, 16:23
Zur ersten Frage: Windows und UNIX (damit auch Cygwin) verwenden unterschiedliche Codierungen für Zeilenwechsel; unter Windows wird CRLF (ASCII 13/10), unter UNIX nur LF (ASCII 10) verwendet. In einigen Windows-Programmen wird eine mit UNIX-Tools erstellte/bearbeitete Datei deshalb so aussehen, als wären die Zeilenumbrüche verschwunden.
Konvertieren lassen sich die Zeilenumbrüche z.B. mit dos2unix/unix2dos und recode.
An deinem größeren Script fallen mir zwei Probleme auf:
- Die Shebang-Zeile (ganz am Anfang) stimmt so nicht; du kannst das Script zwar so problemlos z.B. per "bash abc.sh" ausführen, aber nicht direkt. Korrekt wäre: #!/bin/bash
- Du leitest die sed-Ausgabe nach TEMP bzw. AUSGABE um; in Wirklichkeit willst du aber wohl nach $TEMP und $AUSGABE umleiten. :)
Bad_Rockk
12.07.2010, 07:19
Hallo Jan,
seit dem ersten Post bin ich schon wesentlich weiter gekommen.
Das mit den Zeilenumbrüchen habe ich auch feststellen müssen, arbeite mit Notepad++ und da kann man einstellen was man möchte. Standardmäßig ist da CRLF eingestellt, wenn man das auf LF umstellt kommen daraus keine Probleme mehr.
Hier mal mein aktueller Code:
#!/bin/sh
#
SKRIPT_DIR=`dirname $0`
INPUT_FILE=$SKRIPT_DIR/eingabe.txt
AWK_FILE=$SKRIPT_DIR/ersetzen.awk
VARIA_FILE=$SKRIPT_DIR/tabelle.txt
TEMPLATE_FILE=$SKRIPT_DIR/template.txt
RESULT_DIR=$SKRIPT_DIR/results
echo SKRIPT_DIR : $SKRIPT_DIR
echo DATEI : $DATEI
echo VARIA_FILE : $VARIA_FILE
echo TEMPLATE_FILE : $TEMPLATE_FILE
echo > $AWK_FILE
#Anzahl der Variationen auslesen
NR_VARIA=`awk '{if (NF>0) print}' $VARIA_FILE | awk 'END {print NR-1}'`
echo $NR_VARIA
#Namen der Variablen auslesen
VAR_NAMES=`awk '{if (NR==1) print}' $VARIA_FILE`
echo $VAR_NAMES
START=1
j=$START
# Jede Zeile ab der zweiten aus VARIA_FILE
# auslesen und den Variablennamen zuordnen
while [ $j -le $NR_VARIA ]; do
let LAUF=$j
let ZEILE=$j+1
VAR_VALUES=`sed -n "$ZEILE"p $VARIA_FILE`
k=1
# Kommandozeile zum Aufruf von AWK_FILE zusammenbasteln. Variablen werden
# als Parameter übergeben. Aufruf erfolgt in der Form:
# "awk -f $AWK_FILE varname1=varvalue1 varname2=varvalue2 $TEMPLATE_FILE > $INPUT_FILE"
AWK_LINE="awk -f $AWK_FILE "
for i in $VAR_NAMES; do
VAR_VALUE=`echo "$VAR_VALUES" | cut -f $k`
AWK_LINE=`echo $AWK_LINE "$i=$VAR_VALUE "`
let k=$k+1
done
echo
AWK_LINE=`echo $AWK_LINE $TEMPLATE_FILE`
# Erstellen des INPUT_FILE
$AWK_LINE > $INPUT_FILE
# Erstellen des Ergebnis-Verzeichnis
if [ echo find $SKRIPT_DIR -name "results" ="./results" ]then rm $RESULTS_DIR *
if [ echo find $SKRIPT_DIR -name "results" = ]then mkdir $SKRIPT_DIR/results
let LAUF=`echo "$VAR_VALUES" | cut -f 1`
mkdir $RESULT_DIR/L$LAUF
# Bewegen von $INPUT_FILE in das Ergebnis-Verzeichnis
mv $INPUT_FILE $RESULT_DIR/L$LAUF
let j=$j+1
# Aufräumen
rm $AWK_FILEDa habe ich noch irgendwo einen Fehler drin, bekomme die Fehlermeldung: Unexpected end of file!
edit:
Also der Fehler ist irgendwo in der while Bedingung eingebaut. Da fehlt irgendwo ein "done". Vom Gefühl her, müsste das vor das #aufräumen, aber da bekomme ich dann: synthax error near unexpected token 'done'!
Gruß
Ist doch sonnenklar. Du hast da zwei Schleifen und beendest aber nur eine davon. Wie du richtig bemerkt hast, fehlt ein done.
Die Frage ist nun, willst du, dass die Schleifen geschachtelt sind, oder nicht. So wie du deinen Code formatierst (sehr unübersichtlich) ist das nicht wirklich erkennbar. Also entweder, du beendest die while Schleife ordentlich, bevor die zweite betreten wird oder du musst ein done am Ende setzen.
Bad_Rockk
12.07.2010, 10:45
Hallo,
das Skript ist recht unübersichtlich, da ich es mir aus mehreren verschiedenen Quellen zusammengebastelt habe. Bin wie oben schon gesagt, recht neu in der ganzen Materie.
Die Schleifen sollen schon ineinander liegen.
Aber wie schon im vorherigen Beitrag geschrieben, wenn ich ein weiteres done einfüge, dann bekomme ich die Fehlermeldung: syntax error near unexpected token 'done'
Fehler ist mir ja bewusst, aber wie ich den behebe ist das Problem. Weil der done befehl muss nach meinem let j=$j+1 stehen, da ich ja dadurch die mehreren Durchläufe realisiere.
Gruß
Falsch.
Wenn du das done nach den let Anweisungen setzt, wird die Schleife immer nur bis dahin ausgeführt und das willst du ja offensichtlich nicht. Also musst du es mal mindestens nach der for-Schleife setzen. Wo aber genau, musst du halt einfach selber wissen. Wenn z.B. die if-Anweisungen für jeden Schleifendurchlauf ausgeführt werden sollen, kommt das done ganz ans Ende.
Rücke deinen Code mal ordentlich ein, dann sollte sich automatisch ergeben, was wann ausgeführt werden soll.
Bad_Rockk
12.07.2010, 15:19
Hallo,
bin jetzt mittlerweile schon ein wenig weiter gekommen. Das Skript läuft, macht aber noch nicht das was es soll.
Hier mal der aktuelle Code:
#!/bin/sh
#
set -x
SKRIPT_DIR=`dirname $0`
RESULT_DIR=$SKRIPT_DIR/results
INPUT_FILE=$SKRIPT_DIR/eingabe.txt
AWK_FILE=$SKRIPT_DIR/ersetzen.awk
VARIA_FILE=$SKRIPT_DIR/tabelle.txt # Werte durch Tabulatoren trennen
TEMPLATE_FILE=$SKRIPT_DIR/template.txt
TEMP_FILE=$SKRIPT_DIR/temp.txt
echo SKRIPT_DIR : $SKRIPT_DIR
echo VARIA_FILE : $VARIA_FILE
echo TEMPLATE_FILE : $TEMPLATE_FILE
#Anzahl der Variationen auslesen
NR_VARIA=`awk '{if (NF>0) print}' $VARIA_FILE | awk 'END {print NR-1}'`
echo $NR_VARIA
#Namen der Variablen auslesen
VAR_NAMES=`awk '{if (NR==1) print}' $VARIA_FILE`
echo $VAR_NAMES
#altest RESULT_DIR löschen
rm -fr $RESULT_DIR
mkdir $SKRIPT_DIR/results
##########################################################################
# AWK_FILE zusammenbasteln (muss nur einmal gemacht werden)
##########################################################################
echo "#!/bin/awk -f" > $AWK_FILE
echo >> $AWK_FILE
echo "{" >> $AWK_FILE
for i in $VAR_NAMES; do
echo "gsub("$i",$i,\$0)" >> $AWK_FILE
done
echo "print \$0" >> $AWK_FILE
echo "}" >> $AWK_FILE
START=1
j=$START
# Jede Zeile ab der zweiten aus VARIA_FILE
# auslesen und den Variablennamen zuordnen
# solange $j kleiner $NR_VARIA mache ...
while [ $j -le $NR_VARIA ]; do
LAUF=$j
let ZEILE=$j+1
echo
echo "**********************************************************"
echo "* Lauf $LAUF von $NR_VARIA"
echo "**********************************************************"
# VAR_VALUES anhand der aktuellen Zeile definieren
VAR_VALUES=`sed -n "$ZEILE"p $VARIA_FILE`
echo $VAR_VALUES
# Kommandozeile zum Aufruf von AWK_FILE zusammenbasteln. Variablen werden
# als Parameter übergeben. Aufruf erfolgt in der Form:
# "awk -f $AWK_FILE varname1=varvalue1 varname2=varvalue2 $TEMPLATE_FILE > $INPUT_FILE"
k=1
AWK_LINE="awk -f $AWK_FILE "
for i in $VAR_NAMES; do
FS="/t"
VAR_VALUE=`echo "$VAR_VALUES" | cut -f $k`
AWK_LINE=`echo $AWK_LINE "$i=$VAR_VALUE "`
let k=$k+1
echo " $i = $VAR_VALUE"
done
echo
AWK_LINE=`echo $AWK_LINE $TEMPLATE_FILE`
# Erstellen des INPUT_FILE
$AWK_LINE > $INPUT_FILE
LAUF=`echo "$VAR_VALUES" | cut -f 1`
mkdir $RESULT_DIR/L$LAUF
# Bewegen von $INPUT_FILE in das Ergebnis-Verzeichnis
mv $INPUT_FILE $RESULT_DIR/L$LAUF
let j=$j+1
done
# Aufräumen
#rm $AWK_FILE
set +x
Das einzige was jetzt noch nicht funktioniert ist das ersetzen der Felder in der Template-Datei. Sonst passt alles, Ordner werden erstellt und richtig benannt, läuft ohne Fehlermeldung durch... irgendwo ist jetzt noch ein Fehler. Arbeite jetzt seit 7 Uhr an dem Skript und da sieht man selbst die klarsten Fehler nicht mehr.
Gruß
Jan Krüger
14.07.2010, 12:18
Dein Verfahren, um zum bestehenden Wert einer Variable noch etwas hinzuzufügen, ist reichlich überkompliziert. Das geht auch einfach so:
AWK_LINE="$AWK_LINE $i=$VAR_VALUE"
Ich vermute, dass sich das Problem leicht in der erzeugten Datei ersetzen.awk erkennen lässt.
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.