PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mehrere Zeilen ausgeben von-bis



Nokman
04-06-2008, 21:23
Hi ich habe eine Datei aufbau ungefähr so

12:55:21 Autofahren
12:56:63 Taxi
session start {
Bla bla
{
Bla Bla
Bla Bla
}
{
bla bla
bla bla
}
}
13:20:00 blabiblub
...
...
...
session start {
Bla bla
{
Bla Bla
Bla Bla
}
{
bla bla
bla bla
}
}
23:22 oolo


so ungefähr nun soll er mir im grunde ausgeben in eine neue datei vom bereich "session start" bis zu "23:22" wobei die zahl variabel ist was allerdings ja abgrenzbar ist durch "..:.." und das bei jeden mal von "session start" bis zum Anfang der nächsten Zeitrechnung.

Nun ist meine Frage wie könnte ich das am besten Realisieren womit

ContainerDriver
05-06-2008, 08:06
Hallo,

mit awk geht das recht schnell zu lösen, sieht zwar etwas unübersichtlich aus, erfüllt aber seinen Zweck:


[florian@leuchtturm1 tmp]$ cat aufgaben|awk 'BEGIN{i=0; file_name="test"; file_counter=0;} {if (i == 0) {if (match($0,"^session start")){ print $0 > file_name""file_counter; i=1}} else {print $0 > file_name""file_counter; if (match($0,"^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]")) {i=0; file_counter++;}}}'

Die Ausgabe erfolgt in die Dateien test0, test1, ....

Gruß, Florian

jan61
05-06-2008, 20:36
Moin,

hier noch eine andere Variante:


awk ' BEGIN { doit = 0; fn = 0; }
/^session start/ {doit = 1; fn++; }
{ if (doit == 1) print $0 >fn; }
/^[012][0-9]:[0-5][0-9]/ { doit = 0; }' dateiDie Dateinamen sind etwas fantasielos (1..n), das kann man bei Bedarf noch anhübschen.

Jan

EDIT: Da fehlte ein ']' im regulären Ausdruck für die Zeit - danke an ContainerDriver für den Hinweis.

Nokman
11-06-2008, 10:36
Hallo und Danke noch einmal für den Script der soweit geht bis auf eine Kleinigkeit wenn die Uhrzeit 7:24:55 ist will er es nicht beenden sondern erst nach XX Zeilen wenn das Neue wieder Anfängt.


awk ' BEGIN { doit = 0; fn = 0; }
/^session start/ {doit = 1; fn++; }
{ if (doit == 1) print $0 >fn; }
/^[012]*[0-9]:[0-5][0-9]:[0-5][0-9]/ { doit = 0; }' datei

Also im grunde war ich der Meinung durch hinzufügen des * muss der Parameter nicht umbedingt vorkommen aber er ignoriert es anscheinend.

Noch mal Danke für den Script und Entschuldigung das ich mich erst jetzt melde aber ich hatte viel um die Ohren mit der Arbeit noch mals Danke.

Edit: nachdem ich nun gute 6 Stunden schlaf hate ist es mir eingefallen


awk ' BEGIN { doit = 0; fn = 0; }
/^session start/ {doit = 1; fn++; }
{ if (doit == 1) print $0 >fn; }
/^[ 012][0-9]:[0-5][0-9]:[0-5][0-9]/ { doit = 0; }' datei
mit Hilfe des " " (leerzeichen) vor der 012wird die Freie stelle da es sich um ein leerzeichen handelt auch akzeptiert Danke.

Edit2:

Trotzdem habe ich noch ne kleien Frage wie bekomme ich die Ausgabe in einen neuen Unterordner namens ./tmp um die übersicht zu behalren.

ContainerDriver
11-06-2008, 19:06
Hallo,

an der Stelle


print $0 >fn;

wird die Ausgabe in die Datei umgelenkt, für den Unterordner kannst du schreiben


print $0 >"tmp/"fn;
.

Gruß, Florian

jan61
11-06-2008, 20:48
Moin,


...Also im grunde war ich der Meinung durch hinzufügen des * muss der Parameter nicht umbedingt vorkommen aber er ignoriert es anscheinend.

Nein, dann passt das Suchpattern nicht mehr, wenn am Anfang ein Leerzeichen steht. Das Pattern /^[012]... sagt, dass am Zeilenanfang eine Ziffer 0, 1 oder 2 stehen muss. Wenn Du * hinzufügst, dann kommt die nächste Stelle zum Zug ([0-9]), die dann aber auch am Zeilenanfang stehen muss. Deine Idee, das Leerzeichen in die Gruppe der erlaubten Zeichen einzufügen, ist für diese Situation schon die richtige.

Jan

Nokman
11-06-2008, 23:40
jo Danke Jan ich bin hier nebenbei immer noch am buch durchlesen "Shell-Scripte Programmierung" und komme jeden tag weiter und verstehe mehr :D

nun noch als kleine randfrage kann ich mir die höste Zahl ausgeben lassen die in einen Ordner vorhanden ist da er ja nun Zahlen aufwerts macht müsste ich doch ihm auch sagen bei welcher zahl schluss ist.

Mfg
Andre

Edit am schönsten sind noch immer die eigenen lösungen :D

expr `find ./tmp2 -type f | wc -l` + 1

nun habe ich aber ein anderes problem wo ich keine lösung sehe und zwar will ich überprüfen per if abfrage ob ein Ordner exestiert. Soweit kein problem if [ -d "player/$player" ] soweit hat es hin wenn es sich dabei um namen handelt die "normal" sind.

Sollte nun ein Name aber Bla! heisen hat er Probleme die abfrage zu machen oder wenn der Name "Bla.bli.Blub [Pustekuchen]" ist lässt er den letzten teil weg obwohl es aber in "" gesetzt ist womit er den gesammten namen ja auslesen sollte.

jan61
12-06-2008, 17:53
Moin,

die letzte Frage zuerst: Doch, das funktioniert:

jan@jack:~/tmp/muell_namen> touch 'Bla.bli.Blub [Pustekuchen]'
jan@jack:~/tmp/muell_namen> touch 'Bla!'
jan@jack:~/tmp/muell_namen> cd ..
jan@jack:~/tmp> ls -l muell_namen/
insgesamt 0
-rw-r--r-- 1 jan users 0 2008-05-20 19:50 123'(456\(b l a)
-rw-r--r-- 1 jan users 0 2008-05-20 19:50 123'(456\(bla)
-rw-r--r-- 1 jan users 0 2008-05-20 19:58 123 "buh" 456
-rw-r--r-- 1 jan users 0 2008-06-12 18:35 Bla!
-rw-r--r-- 1 jan users 0 2008-06-12 18:35 Bla.bli.Blub [Pustekuchen]
jan@jack:~/tmp> d='Bla.bli.Blub [Pustekuchen]'
jan@jack:~/tmp> [ -f "muell_namen/$d" ] && echo existiert
existiert
Ich nehme an, dass Dein Fehler eher in der Zuweisung an die Variable $player liegt. Bei Sonderzeichen musst Du streng auf das Entwerten achten. Wie machst Du das denn?

Zu Deiner Lösung wegen der höchsten Nummer in einem Verzeichnis 2 Hinweise: Das funktioniert nur dann, wenn die Nummern tatsächlich fortlaufend sind, also keine Lücke existiert. Und für das Auflisten innerhalb eines Verzeichnis (wenn Du das nicht rekursiv über alle Unterverzeichnisse machen willst), dann ist find etwas oversized, ein einfacher ls würde es auch tun (vorausgesetzt, es sind keine Unterverzeichnisse vorhanden).

So z. B. kannst Du die tatsächliche höchste Nummer in einem Verzeichnis finden:
jan@jack:~/tmp/num_namen> touch `seq 1 123`
jan@jack:~/tmp/num_namen> rm 42 23 66
jan@jack:~/tmp/num_namen> ls | sort -n | tail -n 1
123
Der 1. Befehl legt Dateien mit den Nummern 1 .. 123 an, der 2. löscht ein paar. Mit dem letzten Befehl listest Du die Dateien auf, sortierst sie numerisch (sonst ist "10" < "2") und schnippelst dann alles bis auf die letzte Zeile weg.

Jan

Nokman
12-06-2008, 18:04
player=`sed -r 's/[^"]*"([^"]*)";/\1/' "tmp2/"27 | sed -n '3p'`

ich suche mir die 3 zeile raus aus tmp2/27 dort suche ich mir den inhalt zwischen "..."; und setze ihn in die Variable soweit geht es ja der Inhalt in der Variable per echo ausgegeben haut ja auch hin


if [ -d "player/$player" ]
then
echo "ist da"
else
echo "ist nicht da"
fi

jan61
12-06-2008, 18:38
Moin,

geht bei mir trotzdem (ich habe Deine 2 sed mal zu einem zusammengefasst):

jan@jack:~/tmp/num_namen> cat 27
1
2
Bla.bli.Blub [Pustekuchen]
4
5
jan@jack:~/tmp/num_namen> ls -l B*
-rw-r--r-- 1 jan users 0 2008-06-12 19:32 Bla.bli.Blub [Pustekuchen]
jan@jack:~/tmp/num_namen> f=`sed -rn 's/[^"]*"([^"]*)";/\1/;3p' 27`
jan@jack:~/tmp/num_namen> echo $f
Bla.bli.Blub [Pustekuchen]
jan@jack:~/tmp/num_namen> test -f "./$f" && echo ok
ok
Jan

Nokman
12-06-2008, 19:19
habe es gerade probiert und ja es geht mit touch aber nicht wenn ich einen ordner anlege mit mkdir


nokman@gbe-clan:/games/bastel/player$ touch "ba-bi.bu [Blau]"
nokman@gbe-clan:/games/bastel/player$ mkdir "ba-bi.bu [Rot]"
nokman@gbe-clan:/games/bastel/player$ ls -l
total 4
-rw-r--r-- 1 nokman nokman 0 2008-06-12 20:27 ba-bi.bu [Blau]
drwxr-xr-x 2 nokman nokman 4096 2008-06-12 20:27 ba-bi.bu [Rot]
nokman@gbe-clan:/games/bastel/player$ a='ba-bi.bu [Blau]'
nokman@gbe-clan:/games/bastel/player$ b='ba-bi.bu [Rot]'
nokman@gbe-clan:/games/bastel/player$ [ -f "$a" ] && echo existiert
existiert
nokman@gbe-clan:/games/bastel/player$ [ -f "$b" ] && echo existiert
nokman@gbe-clan:/games/bastel/player$


ps: ähm mein fehler ich muss den Parameter ja auch -d abändern für Ordner


aber trotzdem will es nicht

player=`sed -rn 's/[^"]*"([^"]*)";/\1/;3p' tmp2/27`
user="player/$player"
echo $user
ls "$user"
if [ -d '$user' ]
then
echo "ist da"
else
echo "ist nicht da"
fi

die ausgabe


nokman@gbe-clan:/games/bastel$ ls -l player
total 4
-rw-r--r-- 1 nokman nokman 0 2008-06-12 20:27 ba-bi.bu [Blau]
drwxr-xr-x 2 nokman nokman 4096 2008-06-12 20:27 ba-bi.bu [Rot]
nokman@gbe-clan:/games/bastel$ ./script2
player/ba-bi.bu [Rot]
: No such file or directory
ist nicht da
nokman@gbe-clan:/games/bastel$
nokman@gbe-clan:/games/bastel$ user='player/ba-bi.bu [Rot]'
nokman@gbe-clan:/games/bastel$ [ -d "$user" ] && echo existiert
existiert
nokman@gbe-clan:/games/bastel$
jetzt die frage Warum?

Edit: ich habe das Problem nun eingegrenzt
if test -r /games/bastel/player/$player/; then
wenn ich den namen (test) nun selber einsetzte geht es

jan61
12-06-2008, 23:13
Moin,

funktioniert trotzdem:
jan@jack:~/tmp/num_namen> mkdir 'Bla.bli.Blub [Flaschenhals]'
jan@jack:~/tmp/num_namen> ls -ld B*
drwxr-xr-x 2 jan users 4096 2008-06-12 23:58 Bla.bli.Blub [Flaschenhals]
-rw-r--r-- 1 jan users 0 2008-06-12 19:32 Bla.bli.Blub [Pustekuchen]
jan@jack:~/tmp/num_namen> cat 27
1
2
Bla.bli.Blub [Flaschenhals]
4
jan@jack:~/tmp/num_namen> f=`sed -rn 's/[^"]*"([^"]*)";/\1/;3p' 27`
jan@jack:~/tmp/num_namen> echo $f
Bla.bli.Blub [Flaschenhals]
jan@jack:~/tmp/num_namen> test -d "./$f" && echo ok
ok
Guck Dir bitte mal an, wie in der Shell "" und '' wirken. In '' wird nämlich nichts mehr ausgewertet, deshalb sucht Dein test nach einem Verzeichnis mit Namen $user - das gibts nicht.

Jan

P.S.: Schau Dir mal an, was die Shell wirklich macht. Setze ganz an den Anfang der Scripts ein "set -x", dann protokolliert die Shell jede einzelne Zeile, die sie ausführt.

Nokman
13-06-2008, 01:36
#! /bin/bash
set -x
player=`sed -rn 's/[^"]*"([^"]*)";/\1/;3p' tmp2/27`
echo $player
if [ -d player/$player/ ] ;then
echo "ist da"
echo $player > test.txt
else
echo "ist nicht da"
echo $player > test.txt
fi

so sieht das script nun aus

und das ist die ausgabe

nokman@gbe-clan:/games/bastel$ ./script2
++ sed -rn 's/[^"]*"([^"]*)";/\1/;3p' tmp2/27
+ player=$'test\r'
+ echo $'test\r'
test
+ '[' -d $'player/test\r/' ']'
+ echo 'ist nicht da'
ist nicht da
+ echo $'test\r'


inhalt der dabei test.txt ist test.

Ich bin mittlerweile echt etwas überfragt wo der fehler ist


nokman@gbe-clan:/games/bastel$ ./script2
++ sed -rn 's/[^"]*"([^"]*)";/\1/;3p' tmp2/27
+ player=$'test\r'
+ echo $'test\r'
test
+ '[' -d $'player/test\r/' ']'
+ echo 'ist nicht da'
ist nicht da
+ echo $'test\r'
nokman@gbe-clan:/games/bastel$ nano script2
nokman@gbe-clan:/games/bastel$ ./script2
++ sed -rn 's/[^"]*"([^"]*)";/\1/;3p' tmp2/27
+ player=$'test\r'
+ echo $'test\r'
test
+ '[' -d player/test/ ']'
+ echo 'ist da'
ist da
+ echo $'test\r'

da geht es ich habe nur $player gegen test ausgetauscht und es geht

jan61
14-06-2008, 23:23
Moin,

Dein Problem liegt glaube ich an einer ganz anderen Stelle. Sind Dir die vielen '\r' in der bash-Ausgabe aufgefallen? Das sind Reste des DOS-Zeilenende CR-LF ('\r\n')- es handelt sich also ganz offenbar um Dateien, die von einem M$-System kommen. Unter Unix/Linux ist allein Linefeed ('\n') für das Zeilenende verantwortlich, d. h. alle Suchmuster, die durch z. B. sed am Ende einer Zeile gefunden werden, enthalten als letztes Zeichen das '\r' - die Zeile ist unter Unix ja noch nicht zu Ende! Damit kannst Du natürlich keine Dateien finden.

Ein Weg, diese Dinger wegzukriegen, geht so:
player=`tr -d '\r' <tmp2/27 | sed -rn 's/[^"]*"([^"]*)";/\1/;3p'`Nützlich, so ein Shell-Debug, wenn man sich die Ausgabe mal genau anguckt, ne?;)

Jan

Nokman
15-06-2008, 00:36
JA das schon nur muss man sie verstehen und ich hate nie gedacht das eine Dos datei einen Fehler verursachen kann. Ich wuste das es probleme gibt wenn die datei einen script enhält das er nicht ausgeführt werden kann aber so. Naja nun wei sich es was es zu bedeuten hat.

Danke