ubuntuusers.de

Bash-Script search & replace

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

dusselmann

Anmeldungsdatum:
6. Mai 2005

Beiträge: 1055

Hallo zusammen,

ich brauche ein Bash-Script, welches aus einer CSV-Datei Werte ausliest (2 Spalten pro Zeile) und dann ein Verzeichnis nach Dateiinhalten mit dem Wort aus der ersten Spalte sucht und dieses Wort mit dem Wort aus Spalte 2 ersetzt. Folgendes hab ich schon gefunden:

cat $1 > /dev/null

while read LINE
do

  search=`echo $LINE | cut -d ";" -f1`
  replace=`echo $LINE | cut -d ";" -f2 | cut -d " " -f1`

  for i in $2
  do
    sed -i 's/$search/$replace/g' $i
  done

done < $1

Würde das funktionieren? Geht es auch "eleganter"?

Brauche dringend Hilfe! Danke schon mal!

Gruß, Dussel

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Machs nicht in der Bash. Nein. Nein. Nein.

Schonmal daran gedacht, was das Script bei

foo;bar;fo\;obaz


tut?

MrKanister

Anmeldungsdatum:
13. Oktober 2007

Beiträge: 2105

Hallo,

cat $1 > /dev/null 


Ws bringt das?

  for i in $2
  do
    sed -i 's/$search/$replace/g' $i
  done 


sed verändert nur den Puffer, nicht die Dateien. Lies besser den Namen der Datei komplett ein. ($ALTER_NAME) dann veränder ihn mit sed nach deinen Vorstellungen (so wie dus mit sed schon vorhattest) und speicher den Namen in einer neuen Variable ($NEUER_NAME).
Dann benutzt zum umbennen "mv"

mv "$ALTER_NAME" "$NEUER_NAME"
done < $1


Mit welchen Parametern willst du dein Skript starten? Wenn du den Pfad der CSV-DAtei mit angeben willst, dann mach

done < cat "$1"
for i in $2 


In $2 sollen also die Namen aller Dateien sein, auf die der Name zutrifft? Nimm besser eine while-Schleife (auch wegen möglichen Leerzeichen)

find /PFAD/ZU/DEN/DATEIEN -name "${search}*" | while read ZEILE

...und dann wie gesagt mit "mv"

Wenn du noch genaueres brauchst, einfach melden 😉

Gruß Martin

comm_a_nder

Avatar von comm_a_nder

Anmeldungsdatum:
5. Februar 2006

Beiträge: 2533

Wohnort: Dresden

audax hat geschrieben:

Machs nicht in der Bash. Nein. Nein. Nein.

Schonmal daran gedacht, was das Script bei

foo;bar;fo\;obaz


tut?

Mit welchen programmiersprachlichen Mittel würdest Du solch ein kapottes csv bearbeiten?

comm_a_nder

Avatar von comm_a_nder

Anmeldungsdatum:
5. Februar 2006

Beiträge: 2533

Wohnort: Dresden

Mr. Kanister hat geschrieben:

  for i in $2
  do
    sed -i 's/$search/$replace/g' $i
  done 


sed verändert nur den Puffer, nicht die Dateien. Lies besser den Namen der Datei komplett ein. ($ALTER_NAME) dann veränder ihn mit sed nach deinen Vorstellungen (so wie dus mit sed schon vorhattest) und speicher den Namen in einer neuen Variable ($NEUER_NAME).

Du willst mal nachschauen, was -i bei sed bewirkt ... 😉

comm_a_nder

Avatar von comm_a_nder

Anmeldungsdatum:
5. Februar 2006

Beiträge: 2533

Wohnort: Dresden

meine adhoc Lösung (ohne jegliche Fehlerprüfungen und ohne es getestet zu haben):

while read LINE
do
    sed_command=$(echo "$LINE" | awk -F';' '{print "s/"$1"/"$2"/g"}')
    find "$2" -type f -exec sed -e $sed_command {} \;
done < "$1"

dusselmann

(Themenstarter)

Anmeldungsdatum:
6. Mai 2005

Beiträge: 1055

comm_a_nder hat geschrieben:

meine adhoc Lösung (ohne jegliche Fehlerprüfungen und ohne es getestet zu haben):

while read LINE
do
    sed_command=$(echo "$LINE" | awk -F';' '{print "s/"$1"/"$2"/g"}')
    find "$2" -type f -exec sed -e $sed_command {} \;
done < "$1"

herrje, sieht kompliziert aus. wie gesagt, ich möchte die dateien nicht umbenennen, sondern deren inhalte manipulieren. das hab ich jetzt:

while read LINE
do

  search=`echo $LINE | cut -d ";" -f1`
  echo rv search $LINE: $search $?
  replace=`echo $LINE | cut -d ";" -f2 | cut -d " " -f1`
  echo rv replace $LINE: $replace $?

  for i in $(find . -type f -name "$2" )
  do
    sed -i "s/$search/$replace/g" $i
    echo rv sed $i: $?
  done

done < $1


das funktioniert auch, bis auf: er liest nur 1 (von 2) dateien ein und ändert diese. die 2. berührt er nicht. warum?

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

comm_a_nder hat geschrieben:

audax hat geschrieben:

Machs nicht in der Bash. Nein. Nein. Nein.

Schonmal daran gedacht, was das Script bei

foo;bar;fo\;obaz


tut?

Mit welchen programmiersprachlichen Mittel würdest Du solch ein kapottes csv bearbeiten?

Auch bei csv kann man mit dem Backslash Zeichen escapen.

Ich würd Python/Perl nehmen.

dusselmann

(Themenstarter)

Anmeldungsdatum:
6. Mai 2005

Beiträge: 1055

audax hat geschrieben:

Ich würd Python/Perl nehmen.

ich brauche es als bash script

comm_a_nder

Avatar von comm_a_nder

Anmeldungsdatum:
5. Februar 2006

Beiträge: 2533

Wohnort: Dresden

audax hat geschrieben:

Auch bei csv kann man mit dem Backslash Zeichen escapen.

Ich würd Python/Perl nehmen.

Probier es mal bitte in Python oder Perl, hab gerade keine Gelegenheit dazu.
Der csv Import in OpenOffice zB versagt bei Deinem Beispiel

dusselmann

(Themenstarter)

Anmeldungsdatum:
6. Mai 2005

Beiträge: 1055

so, es funktioniert:

while read LINE
do

  search=`echo $LINE | cut -d ";" -f1`
  echo rv search $LINE: $search $?
  replace=`echo $LINE | cut -d ";" -f2 | cut -d " " -f1`
  echo rv replace $LINE: $replace $?

  for i in $(find . -type f -name "$2" )
  do
    sed -i "s/$search/$replace/g" $i
    echo rv sed $i: $?
  done

done < $1

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

comm_a_nder hat geschrieben:

audax hat geschrieben:

Auch bei csv kann man mit dem Backslash Zeichen escapen.

Ich würd Python/Perl nehmen.

Probier es mal bitte in Python oder Perl, hab gerade keine Gelegenheit dazu.
Der csv Import in OpenOffice zB versagt bei Deinem Beispiel

Da CSV kein echter Standard ist, sagt man den Python/Perl-Parsern einfach, welche Symbole escapen 😉

Afflux

Anmeldungsdatum:
5. Juni 2006

Beiträge: 119

Wohnort: Reiskirchen

audax hat geschrieben:

Da CSV kein echter Standard ist, sagt man den Python/Perl-Parsern einfach, welche Symbole escapen 😉

RFC 4180

Sid_Burn

Anmeldungsdatum:
23. Oktober 2004

Beiträge: 2159

Also wie audax schon sagte sind CSV Dateien etwas kompliziertes und ein Reines Splitten ist nicht ganz Korrekt. Und ein Beispiel das auch out-of-the-boc mit OpenOffice.org läuft ist folgende zeile.

David;Raab;"Perl; Programmierer";"Jetzt kann man "";"" im Datensatz nutzen";24

Das ganze obere Beispiel hat dann 5 Spalten anstatt 7 wie ein reines Splitt machen würde. und Funktioniert so auch in OpenOffice.org. Aber auch in OpenOffice.org kann man beim importieren angeben welches Zeichen als escape dient. In der Regel wenn im Datensatz allerdiengs das Trennsymbol vorkommt setzt man das ganze z.B. in Hochkommata. Soll ein Hochkommate im String vorkommen werden zwei aufeinanderfolgende Hochkommata genutzt um es zu escapen. Die obere Zeile ist so angepasst wie OpenOffice.org Default Arbeitet "Insert->Sheet From File"

Man kann zwar eine Regex zusammenbauen die das auslesen kann (zumindest in Perl) aber viel Spaß dabei....

In Perl kann man dafür dann z.B. Text::CSV_XS nutzen.

Afflux hat geschrieben:

audax hat geschrieben:

Da CSV kein echter Standard ist, sagt man den Python/Perl-Parsern einfach, welche Symbole escapen 😉

RFC 4180

Ein RFC ist kein Standard. 😉
RFC steht für "Request for Common" (anfrage nach einem Standard). Standards fangen mit STD an.

Ansonsten ist eine RFC ja toll, wenn sich aber keiner daran hält was nunmal oft der Fall ist, und jeder andere Trennzeichen etc. nimmt dann bringt einem ein RFC Dokument auch nichts.

Afflux

Anmeldungsdatum:
5. Juni 2006

Beiträge: 119

Wohnort: Reiskirchen

Sid Burn hat geschrieben:

Ein RFC ist kein Standard. 😉
RFC steht für "Request for Common" (anfrage nach einem Standard). Standards fangen mit STD an.

Ansonsten ist eine RFC ja toll, wenn sich aber keiner daran hält was nunmal oft der Fall ist, und jeder andere Trennzeichen etc. nimmt dann bringt einem ein RFC Dokument auch nichts.

RFC steht für "Request for Comments" (anfordern von Kommentaren). However, auf Request for Comments steht: "Bei der ersten Veröffentlichung noch im ursprünglichen Wortsinne zur Diskussion gestellt, behalten RFC auch dann ihren Namen, wenn sie sich durch allgemeine Akzeptanz und Gebrauch zum Standard entwickelt haben."

In diesem speziellen Fall fiel mir tatsächlich aber erst nachher auf, dass dieser RFC eher beschreibender als standardisierender Natur ist ("An attempt at a common definition", wie es in eben diesem o.g. Dokument steht).

Edit: bevor du mir jetzt sagst, dass es trotzdem noch kein ISO/DIN/sonstwas Standard ist, das ist mir schon bewusst. Allerdings könnte man dann bei einigen Protokollen nicht von Standardisierung sprechen, und die "allgemeine Akzeptanz" ist IMHO eine de facto Standardisierung.

Antworten |