Diese Website existiert nur weil wir Werbung mit AdSense ausliefern.
Bitte den AdBlocker daher auf dieser Website ausschalten! Danke.

[gelöst] Variable aus pipe exportieren

Alles rund um die verschiedenen Konsolen und shells sowie die Programmierung unter Linux

Moderator: Moderatoren

Antworten
Graf Zahl
Newbie
Newbie
Beiträge: 14
Registriert: 20. Apr 2009, 20:51

[gelöst] Variable aus pipe exportieren

Beitrag von Graf Zahl »

Hallo zusammen,
ich kämpfe schon ein paar Tage mit folgendem Problem, nun muss ich Euch um Rat fragen:
Mein bash-script soll eine Datei durchsuchen, Zeilen mit bestimmten Wörtern herausfiltern und analysieren. Ich mache das mit folgendem script (Erklärung darunter):

Code: Alles auswählen

COUNTER=0
grep -e "^\[Profile" "~/profile.ini" | while read t     # send lines with "[Profile" to a while loop
do
  t=${t#"[Profile"}             # cut off beginning of line
  t=${t%"]"}                    # cut off end of line (it remains a decimal number)
  if [[ $t -ge $COUNTER ]]      # if the decimal is >=$COUNTER increase $COUNTER accordingly
  then
    let "COUNTER=t+1"
    echo "in loop: "$COUNTER    # debugging info
  fi
done
echo "after loop: "$COUNTER     # debugging info
Die zu parsende Quelldatei ist "~/profile.ini", die Profile-Datei von Firefox (Pfad oben zur Veanschaulichung gekürzt):

Code: Alles auswählen

...
[Profile0]
Name=default
IsRelative=1
Path=12345678.default
Default=1
[Profile1]
Name=test
IsRelative=1
Path=23456789.test
...
Ich suche die höchste Profilnummer in dieser Datei. Dazu interessieren mich nur die Zeilen, die [Profile*] enthalten. Die filtere ich mit grep und schicke sie als $t in die while-Schleife. Dort schneide ich [Profile und ] ab, so dass $t nur noch die Profilnummer ist. Diese vergleiche ich mit $COUNTER, um $COUNTER ggf. zu erhöhen.
Das funktioniert zunächst auch, aber $COUNTER nimmt seinen alten Wert (0) wieder an, sobald man die Schleife verlässt. Während also in der Schleife $COUNTER brav die Werte 1 und 2 annimmt (echo "in loop" ergibt 1 und 2), ist das nach der Schleife wieder vergessen (echo "after loop" ist wieder 0).
Ich habe nun schon eine ganze Weile probiert und gesucht (auch hier), aber leider keine Lösung gefunden. Könnt Ihr mir bitte helfen?
Meine Fragen:
1) Wie musss ich die Variable deklarieren, dass mir das Ergebnis $COUNTER auch nach der Schleife zur Verfügung steht?
2) (Bonusfrage ;-) WARUM ist das so? Es liegt doch bestimmt an der pipe, oder?

Vielen Dank schon vorab für Eure Hilfe!
Markus
Zuletzt geändert von Graf Zahl am 29. Jan 2010, 20:47, insgesamt 1-mal geändert.
Gräfin Klara
Hacker
Hacker
Beiträge: 566
Registriert: 23. Jun 2008, 20:51

Re: Variable aus pipe exportieren

Beitrag von Gräfin Klara »

Ich würde das folgend lösen

Code: Alles auswählen

COUNTER=0

get_count()
{
	COUNTER=0
	while read tline; do
		tline=`expr "$tline" : "^\[[a-zA-Z _]*\([0-9]*\)\]$"`
		if [ "$tline" ]; then
			[ $COUNTER -lt $tline ] && COUNTER=$tline
		fi
	done < $1
}

get_count "~/profile.ini"
echo "after get_count: $COUNTER"     # debugging info

Dein Problem liegt bei grep, aber das ist sowieso ein overkill

Gruß
abgdf
Guru
Guru
Beiträge: 3318
Registriert: 13. Apr 2004, 21:15

Re: Variable aus pipe exportieren

Beitrag von abgdf »

Verarbeitung von Daten aus Dateien mit bash ist doch echt gruselig. Wo es doch z.B. für Perl so schöne Module gibt:

http://search.cpan.org/~shlomif/Config- ... niFiles.pm

Gruß
Graf Zahl
Newbie
Newbie
Beiträge: 14
Registriert: 20. Apr 2009, 20:51

Re: Variable aus pipe exportieren

Beitrag von Graf Zahl »

Danke an Euch beide.

@ Gräfin Klara:
Als Funktion klappt es also. Das ist ja prima! Damit wäre mein Problem auch schon gelöst. Gut, dasss ich hier nicht indirekt referenzieren musste, oder so...

@abgdf:
Ich spreche leider kein Perl - deshalb hab' ich nicht allzuviel auf der Seite hinter Deinem Link verstanden. Aber z.Zt. noch egal, da ich ja dennoch weitergekommen bin - s.o.
In den Sprachen, die ich sonst spreche, muss man Dateien immer erst eine Ressource zuweisen, sie zum Lesen öffen usw. Da finde ich einen Einzeiler zum Lesen und Filtern von Dateien manchmal schon recht praktisch. Insbesondere, wenn es echt nur sowas rudimentäres ist und ich den output direkt für einen shell-Befehl brauche. Bei wilderen Sachen oder größeren Dateien nutze ich dann auch andere Methoden.

Nochmals Danke & viele Grüße,
Markus
Benutzeravatar
haveaniceday
Hacker
Hacker
Beiträge: 775
Registriert: 7. Jul 2004, 14:09
Wohnort: Paderborn

Re: [gelöst] Variable aus pipe exportieren

Beitrag von haveaniceday »

Hallo Ihr,

das Problem bei dem oberen Beispiel ist eine "Besonderheit" bei bash gegenüber ksh.
a=0
cat xx | while read x
do
im loop
let a=a+1
done
echo $a

der "while...done" loop wird immer eine "Subshell" sein. Dadurch wird die Variable "a" zwar in der Subshell geändert,
das "$a" vom echo $a ist jedoch ausserhalb der Subshell.
Bei der ksh würde "while...done" nicht als Subshell laufen und dadurch würde das gewünschte Ergebnis ausgegeben.

Haveaniceday
The gates in my computer are AND,OR and NOT, not Bill.
Wer lesen kann und dann noch die Suche bedienen kann ist klar im Vorteil 8)
abgdf
Guru
Guru
Beiträge: 3318
Registriert: 13. Apr 2004, 21:15

Re: [gelöst] Variable aus pipe exportieren

Beitrag von abgdf »

@Graf Zahl: Würd' Dir gern noch ein Beispiel in Perl zeigen, aber dazu müßtest Du das Modul installieren, und die vielen Sonderzeichen von Perl würden Dich wahrscheinlich verwirren.
Daher hier mal ein Beispiel in Python (meiner Lieblingssprache, die die meisten Module (wie "ConfigParser") gleich mitbringt):

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: iso-8859-1 -*-

import os
import sys
import ConfigParser

# os.getenv("HOME") entspricht dem ~-Verzeichnis:
fname = os.path.join(os.getenv("HOME"), "profile.ini")

if not os.path.isfile(fname):
    print "File '" + fname +"' not found."
    sys.exit(1)

cp = ConfigParser.ConfigParser()
cp.read(fname)

x = 0

for i in cp.sections():
    if i.startswith("Profile") and i != "Profile":
        nr = i.split("Profile")[1]
        if nr.isdigit():
            nr = int(nr)
            if x < nr:
                x = nr
        else:
            print "Warning: Section '" + i + "' contains something after 'Profile', that's not a number!"
            continue

print x
Gruß
Graf Zahl
Newbie
Newbie
Beiträge: 14
Registriert: 20. Apr 2009, 20:51

Re: [gelöst] Variable aus pipe exportieren

Beitrag von Graf Zahl »

@ haveaniceday,
ich meine, das würde auch in der bash funktionieren. Deswegen läuft ja Gräfin Klaras code. Aber auch ausserhalb einer Funktion habe ich das in einem bash-script getestet:

COUNTER=0
while read t; do
# mach irgendwas
COUNTER=1
done < infile.txt

Hier ist COUNTER nach der Schleife gleich 1. Mit einer Pipe hingegen:

cat infile.txt | while read t; do
# mach irgendwas
echo $t
COUNTER=1
done

ist COUNTER nach der Schleife gleich 0. Während ein redirect klappt, ist bei einer pipe also Ende. Da habe ich wieder was gelernt.
___
@abgdf
Danke für den code! Soo verwirrend ist das eigentlich nicht, hat ja was von c. Und wie schon erwähnnt nutze ich bei Bedarf auch Programmimersprachen, um komplexere Probleme zu lösen - nur eben kein Perl. Aber das kann ja noch kommen, die Neugierde ist nun geweckt... ;-)

Viele Grüße
Benutzeravatar
haveaniceday
Hacker
Hacker
Beiträge: 775
Registriert: 7. Jul 2004, 14:09
Wohnort: Paderborn

Re: [gelöst] Variable aus pipe exportieren

Beitrag von haveaniceday »

Etwas spät, aber ich hab ihn noch gefunden: Einen Link mit ein paar Besonderheiten und
Unterschieden in den Shells:
ftp://ftp.cwru.edu/pub/bash/FAQ

"E4" Behandelt dabei das Thema von diesem Thread.

Haveaniceday
The gates in my computer are AND,OR and NOT, not Bill.
Wer lesen kann und dann noch die Suche bedienen kann ist klar im Vorteil 8)
Antworten