Massen-Datei-Reinigungs-Skript-Ding

08/05/2008 - 21:16 von Andreas Döbler | Report spam
Hallo da draußen!

Ich habe mal wieder zwei Bash-Skript-spezifische Fragen, und bin nicht
sicher, ob die unter Unix.Shell eher wilkommen sind, oder hier...

Also, ich hab in meiner freudigen Unkenntnis folgendes fabriziert:



#!/bin/bash

egrep -v "^31;*" $1 > $1_neu
egrep -v "^32;*" $1_neu > $1_neu1
egrep -v "^33;*" $1_neu1 > $1_neu2
egrep -v "^34;*" $1_neu2 > $1_neu3
egrep -v "^36;*" $1_neu3 > $1_neu4

rm -f -v $1_neu $1_neu1 $1_neu2 $1_neu3

-

Das sieht für Kenner bestimmt sehr lustig aus. ;-)
Sinn der Sache ist jedenfalls, dass ich aus mehreren 100 Dateien alle
Zeilen löschen soll, die mit den jeweiligen Wert (also z. B. 32)
beginnen.
Ausgegeben werden soll das ganze dann in eine neue Datei.

1. Frage: Wie kann ich mir die _neu1, 2, 3, etc. sparen, und grep
mehrere Such-Attribute geben?

2. Frage: Wenn ich jetzt das Skript mit "*" als Parameter aufrufe,
erstellt er am Ende nur die Datei *_neu.
grep versteht also keine *, es sei denn man schreibt noch was dazu
(*.txt z. B.)
Glaube ich jetzt jedenfalls.

Nun habe ich was gelesen von einer "for file do"-Schleife, die solange
ausgeführt wird, wie es Dateien im Verzeichnis gibt.
Leider hapert hier die Anwendung wegen eines "ambiguous redirect"...
was daran liegt, dass man $file glaube ich erst noch deklarieren
muss...

Egal: Langer Rede kurzer Sinn: Wie würdet ihr das angehen? Ich find
einfach nichts richtig hilfreiches im WWW, bzw. suche ich wohl mit den
falschen Begriffen.

Vielen Dank im Voraus, und noch einen schönen Abend!

Andi
 

Lesen sie die antworten

#1 Markus Wichmann
08/05/2008 - 21:52 | Warnen spam
Andreas Döbler schrieb:
Hallo da draußen!

Ich habe mal wieder zwei Bash-Skript-spezifische Fragen, und bin nicht
sicher, ob die unter Unix.Shell eher wilkommen sind, oder hier...

Also, ich hab in meiner freudigen Unkenntnis folgendes fabriziert:



#!/bin/bash

egrep -v "^31;*" $1 > $1_neu
egrep -v "^32;*" $1_neu > $1_neu1
egrep -v "^33;*" $1_neu1 > $1_neu2
egrep -v "^34;*" $1_neu2 > $1_neu3
egrep -v "^36;*" $1_neu3 > $1_neu4

rm -f -v $1_neu $1_neu1 $1_neu2 $1_neu3

-

Das sieht für Kenner bestimmt sehr lustig aus. ;-)
Sinn der Sache ist jedenfalls, dass ich aus mehreren 100 Dateien alle
Zeilen löschen soll, die mit den jeweiligen Wert (also z. B. 32)
beginnen.
Ausgegeben werden soll das ganze dann in eine neue Datei.

1. Frage: Wie kann ich mir die _neu1, 2, 3, etc. sparen, und grep
mehrere Such-Attribute geben?




egrep -v "^3[1-6];*"

Warum benutzt du einerseits Regexp, andererseits dann doch lieber
nicht? Anders gefrag: Warum machst du es dir so schwer?

2. Frage: Wenn ich jetzt das Skript mit "*" als Parameter aufrufe,
erstellt er am Ende nur die Datei *_neu.
grep versteht also keine *, es sei denn man schreibt noch was dazu
(*.txt z. B.)
Glaube ich jetzt jedenfalls.




Nö, in UNIX wird der * von der Shell ausgewertet, es sei denn, sie
wird daran gehindert. Wie rufst du das Skript denn auf? Ein * komplett
ohne was sollte zu allen Dateien des Verzeichnisses expandiert werden.
Da dein Skript aber nur $1 behandelt, wird nur die erste Datei
behandelt.

Nun habe ich was gelesen von einer "for file do"-Schleife, die solange
ausgeführt wird, wie es Dateien im Verzeichnis gibt.
Leider hapert hier die Anwendung wegen eines "ambiguous redirect"...
was daran liegt, dass man $file glaube ich erst noch deklarieren
muss...

Egal: Langer Rede kurzer Sinn: Wie würdet ihr das angehen? Ich find
einfach nichts richtig hilfreiches im WWW, bzw. suche ich wohl mit den
falschen Begriffen.

Vielen Dank im Voraus, und noch einen schönen Abend!

Andi



Nochmal zum mitmeißeln: Aus allen Dateien sollen alle Zeilen entfernt
werden, die mit einer Zahl zwischen 31 und 36 beginnen? Das würde ich
so machen:

#!/bin/bash
while [ "$1" ]; do
if [ -f "$1" ]; then
sed -i '/^3[1-6]/d' "$1"
else if [ -d "$1" ]; then
"$0" "$1"/*
fi
shift
done

Das nimmt sich jedes Argument vor und entfernt entwerder alle
entsprechenden Zeilen aus der Datei, wenn das Argument eine Datei ist,
oder ruft sich selbst für alle Dateien des Argumentes auf, wenn es
ein Verzeichnis ist. Auf die Weise kannst du das Skript einfach auf
alle Dateien nebst Verzeichnissen und Unterverzeichnissen loslassen.
Einfach

./skript.sh *

oder

./skript .

(letzteres ist robuster, falls irgendwelche Dateien mit '-' beginnen)

Ach ja, ist das Semikolon hinter der Zahl Pflicht? Falls ja, bitte
noch in die Regexp von sed einarbeiten:

sed -i '/^3[1-6];/d' "$1"

HTH,
Markus
Progress (n.): process through which USENET evolved from smart people in front
of dumb terminals to dumb people in front of smart terminals.

Ähnliche fragen