ubuntuusers.de

String aus Datei auslesen und in Variable speichern

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

tmade

Anmeldungsdatum:
7. August 2007

Beiträge: 72

Hallo,

kann mir jemand sagen wie ich aus einer Datei einen String auslesen kann? Das Problem ist, dass der Dateiname variabel ist - um ein Beispiel zu machen:
XYZ****
XYZ bleibt immer gleich, aber danach variiert der Name an Zeichen und Länge. Außerdem hat die Datei keine Extension, es handelt sich aber um eine Textdatei
(dahinter steht: Einfacher Text)

Wie spreche ich eine solche Datei an?

Wenn das geht möchte ich aus folgendem Code den rot markierten Text auslesen und in einer Variablen abspeichern:

<ASX version="3.0">
<entry>
<ref HREF="mms://213.200.97.108/radiokoeln$livestream.wma?token=[color=#ff0000]207b059d454e00564fcdf263a64c7642[/color]"/>
</entry>
</ASX>

Bin totaler Skript Anfänger!

Liebe Grüße
Tom

Blattlaus

Avatar von Blattlaus

Anmeldungsdatum:
29. März 2006

Beiträge: 1399

grep "<ref HREF" /pfadzurdatei/XYZ* | sed 's/.*token=\(.*\)"\/>/\1/'

Sid_Burn

Anmeldungsdatum:
23. Oktober 2004

Beiträge: 2159

Wie hättest es den gerne?

Mit einer Shell? (sh,bash,zsh,...) oder Perl, Python, Ruby, C, Java, Tcl oder einer beliebigen anderen Sprache?

#!/usr/bin/perl
use strict;
use warnings;
use File::Find::Rule;
use Tie::File;
use Fcntl;

my @files = File::Find::Rule->file              # wir haben es mit einer Datei zu tun
                            ->name( qr/^xyz/i ) # Die mit xyz anfängt
                            ->readable          # Wir können sie lesen
                            ->ascii             # und ist eine Text Datei
                            ->not_empty         # und leere Dateien wollen wir auch nicht
                            ->in( @ARGV );      # wird Rekursiv in dem Verzeichnissen
                                                # geuscht die wir als Parameter übergeben haben

FILE:
for my $filename ( @files ) {
    # Datei öffnen
    tie my @file, 'Tie::File', $filename, mode => O_RDONLY
        or warn "Cannot open file '$filename'\n" and next FILE;

    # Jede Zeile durchgehen
    for my $line ( @file ) {
        # String suchen und wenn gefunden ausgeben
        if ( $line =~ m/ token = ( [0-9a-f]+ ) /xmsi ) {
            print $1, "\n";
        }
    }
}
sidburn@sid:~/perl/ubu$ ./find_string.pl .
207b059d454e00564fcdf263a64c7642

tmade

(Themenstarter)

Anmeldungsdatum:
7. August 2007

Beiträge: 72

Hallo Blattlaus,

das war genau das was ich gebraucht habe! Vielen Dank!!
Kannst du mir vielleicht auch noch den Code erklären? Mir war klar, dass es mit grep geht und habe mir auch die verschiedenen grep-Optionen angeschaut.
Selber wäre ich aber nie darauf gekommen mein Problem zu lösen. Hast du eine gute Anleitung für SH/Bash Skripte mit Beispielen?
Was ich mir bisher ergoogelt habe war viel zu elementar und ohne Beispiele.

@Sid Burn, Dir auch vielen Dank!

Liebe Grüße
Tom

Blattlaus

Avatar von Blattlaus

Anmeldungsdatum:
29. März 2006

Beiträge: 1399

tmade hat geschrieben:

Hallo Blattlaus,

das war genau das was ich gebraucht habe! Vielen Dank!!
Kannst du mir vielleicht auch noch den Code erklären?

Klar.
–-

grep "<ref HREF" /pfadzurdatei/XYZ* | sed 's/.*token=\(.*\)"\/>/\1/'


Als erstes wird der markierte Teil von der Shell auf der es ausgeführt wird vervollständig. Das Stück wird dabei durch alle verfügbaren Dateien auf die es passt, ersetzt. Befinden sich also in "/pfadzudatei/" drei Dateien die mit "XYZ" anfangen steht da hinterher:

grep "<ref HREF" /pfadzurdatei/XYZ_1 /pfadzurdatei/XYZ_2 /pfadzurdatei/XYZ_3  | sed 's/.*token=\(.*\)"\/>/\1/'


Grep kann mit mehreren Inputdateien umgehen, daher ist das keine Problem.

grep "<ref HREF" /pfadzurdatei/XYZ_1 /pfadzurdatei/XYZ_2 /pfadzurdatei/XYZ_3 | sed 's/.*token=\(.*\)"\/>/\1/'


Dann sucht Grep in jeder Datei, die es übergeben bekommen hat, nach einer Zeile auf die das Pattern (der markierte Teil) passt und gibt sie aus. Da würde dann also sowas rausfallen:

<ref HREF="mms://213.200.97.108/radiokoeln$livestream.wma?token=207b059d454e00564fcdf263a64c7642"/> 
<ref HREF="mms://213.200.97.108/radiokoeln$livestream.wma?token=3465059d45gf34324f263a64cdf42"/> 
<ref HREF="mms://213.200.97.108/radiokoeln$livestream.wma?token=asdb059d454asd345323a64c7652"/> 

Jetzt kommt sed an die Reihe und führt für jede Zeile die es per stdin bekommt den Befehl aus (ich trenne den jetzt mal in mehrer Zeilen auf und schreibe kommentare dahintern):

s/			# Ersetze alles auf das foldendes Pattern zutrifft...
.*				# beliebig viele Zeichen
token=			# dann "token="
\(				# Zwischenspeichern:	
.*				# beliebig viele Zeichen
\)				# zwischenspeichern ende
"\/>			# dann "/> (der Slash wurd maskiert)
/			# ...durch
\1				# den Inhalt von Zwischenspeicher 1
/			# ENDE

Und damit bleibt nur der Hash über und wird von sed ausgegeben. Thats it 😉

tmade

(Themenstarter)

Anmeldungsdatum:
7. August 2007

Beiträge: 72

Super Erklärung!! Vielen herzlichen Dank!! Ich verstehe zwar nicht alles, aber ich werde jetzt solange rumprobieren bis ichs checke ☺

Liebe Grüße
Tom

tmade

(Themenstarter)

Anmeldungsdatum:
7. August 2007

Beiträge: 72

Hallo,

nun habe ich noch eine Frage zu grep bzw. sed.

Ich möchte aus der Datei "setup.txt" mit folgendem Inhalt

<KANAL_1_LINK>=http://xyz.com[/color]<ende> <KANAL_1_VOLUME>=5<ende> <KANAL_2_LINK>=http://abc.com[/color]<ende> <KANAL_2_VOLUME>=-3<ende>
.
.
.
usw. die rot markierten Bereiche auslesen und in einer Variablen (VOLUME und URL) abspeichern.
Mit
{{{URL=$(grep "<KANAL_1_LINK>" /pfadzurdatei/setup.txt | sed 's/<KANAL_1_LINK>=\(.*\)<ende>/\1/') VOLUME=$(grep "<KANAL_1_VOLUME>" /pfadzurdatei/setup.txt | sed 's/<KANAL_1_VOLUME>=\(.*\)<ende>/\1/')}}}
funktioniert das auch perfect. Nun würde ich aber gerne das "<ende>", also den zu begrenzenden Text weglassen. Meine neue "setup.txt" soll also folgender maßen aussehen: <KANAL_1_LINK>=http://xyz.com <KANAL_1_VOLUME>=5 <KANAL_2_LINK>=http://abc.com <KANAL_2_VOLUME>=-3 Geht das und wenn ja wie? Außerdem noch eine Kleinigkeit. Kann es sein, dass "[ ]" das bei grep Probleme macht?
Wie kann ich bei z.B. wenn ich bei grep anstatt "<>" das "[]" verwende maskieren? Sollte doch mit [\ gehen, oder?
also Bsp:
grep "[KANAL_1_VOLUME]" /pfadzurdatei/setup.txt Vielen Dank schonmal, besonders an Blattlaus, dem ich verdanke überhaupt soweit gekommen zu sein! Liebe Grüße
Thomas

jerik

Avatar von jerik

Anmeldungsdatum:
19. August 2006

Beiträge: 425

$ ist die regular expression für Zeileende. Sollte also:

sed 's/<KANAL_1_LINK>=\(.*\)$/\1/

funktionieren. (habs nicht getestet). [ und ] müssen escaped werden, wie der /. D.h. benutze \[ und \].

Wenn ich mir aber dein post so anschauen, vermute ich mal das du dir eine eigenständig Setup datei zurecht baust, in der du gewisse parameter speicherst. Diese scheinst du dann wieder einzulesen. Falls das der Fall ist, wählst du hier gerade ein recht *ungünstigen* ansatz. Die meisten scriptsprachen unterstützten das parsen von configurationsfiles von haus aus:
- php: parse_ini_file
- ruby: to_yml
- perl: hat_bestimmt_auch_was
- python: denke_ich_auch

Falls du das in der Bash machen willst, schreib die Daten in eine datei die folgendes format hat:

# Name der Datei Setup.ini
export kanal_1_link="http://xyz.com"
export kanal_1_volume=5
export kanal_2_link="http://abc.com"
export kanal_2_volumen=-3


Danach kannst du die datei mit folgende aufruf in dein Shellscript einbinden

source Setup.ini

. Damit stehen dir dann die variablen kanal_1_link, etc mit den entsprechenden Werten zur Verfügung.

Gruss – jerik

tmade

(Themenstarter)

Anmeldungsdatum:
7. August 2007

Beiträge: 72

Hallo Jerik,

$ ist die regular expression für Zeileende. Sollte also:
Code:
sed 's/<KANAL_1_LINK>=\(.*\)$/\1/
funktionieren. (habs nicht getestet).

Ich kann bestätigen, dass es so funktioniert! ☺

Falls du das in der Bash machen willst, schreib die Daten in eine datei die folgendes format hat:
Code:
# Name der Datei Setup.ini
export kanal_1_link="http://xyz.com"
export kanal_1_volume=5
export kanal_2_link="http://abc.com"
export kanal_2_volumen=-3

Danach kannst du die datei mit folgende aufruf in dein Shellscript einbinden
Code:
source Setup.ini

Das ist genau das was ich gebraucht habe...PERFEKT!!

Vielen vielen herzlichen Dank für den genialen Tip
Thomas

Ps: Ich möchte an dieser Stelle auch dieses Forum sehr lobend erwähnen. Man bekommt hier super qualifizierte Antworten.
Außerdem gibt es hier kein "Konkurenzdenken" im Sinne von "ich weiß es besser und die Antwort von XY ist blöd.." wie ich das von anderen Foren kenne, wo sich Leute immer gleich gegenseitig anpissen wenn einer mal vorher nicht gegoogelt hat oder "unter deren Niveau gepostet hat"...
Danke an euch alle!!

Antworten |