perl - Arrayabfragen wollen nicht funktionieren
perl - Arrayabfragen wollen nicht funktionieren
Hallo,
stehe im Moment irgendwie auf dem Schlauch...
Ich lasse mir über iwconfig eth2 scan alle wlan-Netze die gefunden werden ausgeben bzw. speicher diese in ein @array.
So nun will ich aber nicht alle diese Werte haben, sondern nur ein paar, die mich interessieren. Dies wollte ich dann mit substitute oder match machen.
Z.B. will ich nur den Namen der ESSID haben. Aber ich bekomme als Rückgabewert immer nur eine 1 für jedes Netz.
Zusätzlich wollte ich noch alle Leerzeilen (die ja nicht benötigt werden) im Array entfernen.
stehe im Moment irgendwie auf dem Schlauch...
Ich lasse mir über iwconfig eth2 scan alle wlan-Netze die gefunden werden ausgeben bzw. speicher diese in ein @array.
So nun will ich aber nicht alle diese Werte haben, sondern nur ein paar, die mich interessieren. Dies wollte ich dann mit substitute oder match machen.
Z.B. will ich nur den Namen der ESSID haben. Aber ich bekomme als Rückgabewert immer nur eine 1 für jedes Netz.
Zusätzlich wollte ich noch alle Leerzeilen (die ja nicht benötigt werden) im Array entfernen.
Oh, yeah!
...mmh...
Ich mache zum Beispiel folgendes:
Bei diesem einfachen match sollte doch eigentlich die essid ausgegeben werden oder habe ich einen totalen Denkfehler?
Es wird nämlich immer nur (bei 2 gefundenen Netzen) das hier ausgegeben:
Ich mache zum Beispiel folgendes:
Code: Alles auswählen
@wlan_networks=`iwlist eth2 scanning`;
foreach $k (@wlan_networks)
{
if($essid = $k =~m /ESSID/)
{print $essid, "\n";}
#print $k, "\n";
}
Es wird nämlich immer nur (bei 2 gefundenen Netzen) das hier ausgegeben:
Code: Alles auswählen
1
1
Oh, yeah!
Code: Alles auswählen
if($essid = $k =~m /ESSID/)
so sollte das funktionieren:
Code: Alles auswählen
if($k =~m /ESSID/) {
print $k
}
Code: Alles auswählen
print grep (/ESSID/, `iwlist eth2 scanning`);
gms
Danke.
Habe das ganze jetzt so gelöst (will nämlich so wenig wie möglich auf die unix eigene tools in meinem perl-script zurückgreifen).
Habe dazu auch noch folgendes auf wikipedia gefunden:
Habe das ganze jetzt so gelöst (will nämlich so wenig wie möglich auf die unix eigene tools in meinem perl-script zurückgreifen).
Code: Alles auswählen
@wlan_networks=`iwlist eth2 scanning`;
foreach $k (@wlan_networks)
{
if ($essid = $k =~ s/.*ESSID:"(.*)"/$1/){
print $1, "\n";
}
}
Jetzt muss ich mir nur noch was überlegen, wie ich die ganzen Leerzeilen aus dem @array entfernt bekomme.Nach Verwendung eines Regulären Ausdruckes stehen folgende Sondervariablen zur Verfügung:
* $& – der erkannte String
* $’ – String vor dem erkanntem String
* $' – String nach dem erkanntem String
* $1..$9 – Ergebnisse der geklammerten Subausdrücke
* $+ – der letzte erkannt Subausdruck
* @- – Start-Offsets der Treffer und Subtreffer
* @+ – dazugehörige End-Offsets
Oh, yeah!
Code: Alles auswählen
if ($essid = $k =~ s/.*ESSID:"(.*)"/$1/){
print $1, "\n";
}
Code: Alles auswählen
print $1 if ($k =~ /ESSID:\"(.*)\"/);"
Hi,
Duff hat geschrieben: Jetzt muss ich mir nur noch was überlegen, wie ich die ganzen Leerzeilen aus dem @array entfernt bekomme.
Code: Alles auswählen
@wlan_networks=`iwlist eth2 scanning`;
foreach $k (@wlan_networks)
{
if (length($k)>0){
if ($essid = $k =~ s/.*ESSID:"(.*)"/$1/){
print $1, "\n";
}
}
}
Roland
"Aber wenn du schon so unwissend bist, davon noch nicht gehört zu haben,
so will ich es doch als gut ansehen, daß du lieber einmal töricht fragst,
als weiterhin nichts von etwas zu wissen, das man doch wissen sollte."
aus "Die Edda des Snorri Sturluson", "Gylfis Täuschung"
"Aber wenn du schon so unwissend bist, davon noch nicht gehört zu haben,
so will ich es doch als gut ansehen, daß du lieber einmal töricht fragst,
als weiterhin nichts von etwas zu wissen, das man doch wissen sollte."
aus "Die Edda des Snorri Sturluson", "Gylfis Täuschung"
Die Abrage ob die Länge größer 0 ist, ist implicit auch in dem Match enthaltenroli hat geschrieben:Code: Alles auswählen
if (length($k)>0){ if ($essid = $k =~ s/.*ESSID:"(.*)"/$1/){
Das mit den Leerzeilen tritt mit den arrays gar nicht mehr auf. Die hätte ich ja vielleicht auch irgendwie mit splice aus den arrays entfernen können (glaube ich).
Hatte heute keine Zeit mehr, um das Script weiter schreiben zu können.
Bisher habe ich es so realisiert (bin aber natürlich noch nicht fertig).
Hatte heute keine Zeit mehr, um das Script weiter schreiben zu können.
Bisher habe ich es so realisiert (bin aber natürlich noch nicht fertig).
Code: Alles auswählen
use strict;
use warnings;
my @wlan_networks;
my $k;
my @essid;
my @quality;
# Alle verfügbaren WLAN-Netze aufspüren
#
@wlan_networks=`iwlist eth2 scanning`;
foreach $k (@wlan_networks)
{
# Nach den ESSIDs suchen
if ($k =~ /.*ESSID:"(.*)"/){
push(@essid, $1);
}
# Nach der Empfangsqualität suchen
if ($k =~ /.*Quality.*(\d{2,3}\/\d{3}).*/){
push(@quality, $1);
}
}
print "@essid\n";
print "@quality\n";
Oh, yeah!
Hallo,
habe mal wieder ein wenig weiter an meinem kleinen Script gebastelt. Habe nun die zwei array miteinander verglichen und bekomme dann ein array geliefert, indem nur die übereinstimmungen aus beiden array enthalten sind.
Doch ich würde das ganze gerne in einer Funtkion unterbringen. Doch ich bekomme es nicht so ganz hin. Es wird kein Wert zurück geliefert.
Mit den Einkommentierten Zeilen funktioniert es. Nur nicht, wenn ich es in einer Funktion unterbringen möchte. Weiß auch nicht so genau, wie ich die Funktion aufrufen muss.
habe mal wieder ein wenig weiter an meinem kleinen Script gebastelt. Habe nun die zwei array miteinander verglichen und bekomme dann ein array geliefert, indem nur die übereinstimmungen aus beiden array enthalten sind.
Doch ich würde das ganze gerne in einer Funtkion unterbringen. Doch ich bekomme es nicht so ganz hin. Es wird kein Wert zurück geliefert.
Code: Alles auswählen
# Konfigurierte Netzwerke suchen
# ssid in @array speichern
#
open (IN,"<","/etc/network/interfaces") or die "Kann die Datei /etc/network/interfaces nicht öffnen";
while (<IN>)
{
if ($_ =~ /.*ssid\s+(.*)\s+/){
push(@ssid, $1);
}
}
close (IN);
print "@ssid\n";
#my (@x,@y);
#my (%hash);
#@x=@ssid;
#@y=@essid;
#push(@y,"Kein Wlan");
#print "@y\n";
#$hash{$_}++ for @x;
#my @equal = grep $hash{$_},@y;
#print "@equal\n";
sub array_compare {
my (@x,@y,@z);
my %hash;
push(@y,"Kein Wlan");
print "@y\n";
$hash{$_}++ for @x;
@z=grep $hash{$_},@y;
return @z;
}
my @equal;
@equal=array_compare(@ssid,@essid);
print "----------\n";
print "@equal\n";
Oh, yeah!
Habe es jetzt so gelöst, indem ich den beiden Array @x und @y in der Funktion die beiden Arrays @ssid und @essid zugewiesen habe (dachte aber, dass ich das nicht noch mal expliziet muss). Naja.
Code: Alles auswählen
sub array_compare {
my (@x,@y,@z);
@x=@ssid;
@y=@essid;
my %hash;
$hash{$_}++ for @x;
@z=grep $hash{$_},@y;
return @z;
}
my @equal;
@equal=array_compare(@ssid,@essid);
print "----------\n";
print "@equal\n";
Oh, yeah!
Das Handling der Parameter funktioniert in Perl über Arrays, daher können in Perl auch nicht mehrere Array an eine Funktion übergeben werden.
In der "arrayfunc2" werden daher Array Referenzen verwendet:
Gruß
gms
In der "arrayfunc2" werden daher Array Referenzen verwendet:
Code: Alles auswählen
gms@gms1:~$ cat x.pl
#!/usr/bin/perl
my @a = ( "a","aa","aaa" );
my @b = ( "b","bb","bbb" );
# falsch
sub arrayfunc1(@) {
my (@x,@y)=@_;
print "func1: array1: @x\n";
print "func1: array2: y=@y\n";
}
# richtig
sub arrayfunc2($$) {
my ($xref,$yref)=@_;
print "func2: array1: @$xref\n";
print "func2: array2: @$yref\n";
}
arrayfunc1(@a,@b);
arrayfunc2(\@a,\@b);
gms@gms1:~$
gms@gms1:~$ ./x.pl
func1: array1: a aa aaa b bb bbb
func1: array2: y=
func2: array1: a aa aaa
func2: array2: b bb bbb
gms
Das hat sich so angehört als wärst du unzufrieden mit deiner Lösung.Duff hat geschrieben:Habe es jetzt so gelöst, indem ich den beiden Array @x und @y in der Funktion die beiden Arrays @ssid und @essid zugewiesen habe (dachte aber, dass ich das nicht noch mal expliziet muss). Naja.
die Parameter kannst du bei deiner Lösung übrigens auch weglassen:
Code: Alles auswählen
@equal=array_compare(@ssid,@essid);
Code: Alles auswählen
sub array_compare {
my (@x,@y,@z);
@x=@ssid;
@y=@essid;
gms
Das sollte dann in etwa so gehen:
Code: Alles auswählen
sub array_compare {
my @z;
my $x_ref=shift;
my $y_ref=shift;
my %hash;
$hash{$_}++ for @{$x_ref};
@z=grep $hash{$_}, @{$y_ref};
return @z;
}
my @equal;
@equal=array_compare(\@ssid,\@essid);
print "----------\n";
print "@equal\n";
Danke, aber ich verstehe dass ganze irgendwie nicht so ganz.
Die beiden Zeilen vorallem nicht. Wieso muss ich dem Array was wegnehmen? Was wird denn überhaupt genau weggenommen?
Eine arrayreferenz zeigt doch auf das ganze array oder nicht?
Die beiden Zeilen
Code: Alles auswählen
my $x_ref=shift;
my $y_ref=shift;
Eine arrayreferenz zeigt doch auf das ganze array oder nicht?
Oh, yeah!
Das ist die Parmetterübergabe an die Funktion.
Alternativ kann man auch schreiben:
oder:
oder
Wenn eine Funtion mit Parametteren aufgerufen werden stehen diese in "@_" der funktion zur Verfügung.
Perl ergänzt immer "@_" oder "$_" wenn Parametter gebraucht werden aber keien angeben sind.
Alternativ kann man auch schreiben:
Code: Alles auswählen
my $x_ref=shift(@_);
my $y_ref=shift(@_);
Code: Alles auswählen
my ($x_ref,$y_ref)=@_;
Code: Alles auswählen
my $x_ref=$_[0];
my $y_ref=$_[1];
Perl ergänzt immer "@_" oder "$_" wenn Parametter gebraucht werden aber keien angeben sind.
Stimmt, haette ich vielleicht erwaehnen sollen.
Perl belegt an vielen Stellen $_ und @_ mit Werten, wenn man nichts anderes angibt.
Wenn du mehr ueber eigene Funktionen erfahren willst, solltest du dir auch mal durchlesen.
Da wird einiges rund um Subs erklaert.
Perl belegt an vielen Stellen $_ und @_ mit Werten, wenn man nichts anderes angibt.
Wenn du mehr ueber eigene Funktionen erfahren willst, solltest du dir auch mal
Code: Alles auswählen
perldoc perlsub
Da wird einiges rund um Subs erklaert.
Danke, werde ich machen. Muss nämlich irgendwie noch mal die Zusammenhänge von Referenzen, Hashes und Arrays durchlesen, da noch immer nicht ganz verstehe, wieso man bei einer Referenz auf ein Array, ein shift braucht.nepos hat geschrieben: Wenn du mehr ueber eigene Funktionen erfahren willst, solltest du dir auch maldurchlesen.Code: Alles auswählen
perldoc perlsub
Da wird einiges rund um Subs erklaert.
Oh, yeah!
Nein, das hat nix damit zu tun, dass das ne Referenz ist.
Wenn du eine Funktion aufrufst, dann landen alle Parameter in @_.
Innerhalb der Funktion kommst du ueber diesen Array dran.
Wenn du allerdings sowas machst dann hast du in @_ alle Werte von @foo und @bar stehen. Wie willst du die dann wieder auseinanderklamuesern?
Deshalb musst du in dem Fall statt der Arrays direkt deren Referenzen uebergeben!
In @_ stehen dann nur die Referenzen, die du mit shift in lokale Variablen packen kannst.
Das ganze findest du in der perlsub-Manpage unter "Pass by Reference".
Wenn du eine Funktion aufrufst, dann landen alle Parameter in @_.
Innerhalb der Funktion kommst du ueber diesen Array dran.
Wenn du allerdings sowas machst
Code: Alles auswählen
mySub(@foo,@bar);
Deshalb musst du in dem Fall statt der Arrays direkt deren Referenzen uebergeben!
In @_ stehen dann nur die Referenzen, die du mit shift in lokale Variablen packen kannst.
Das ganze findest du in der perlsub-Manpage unter "Pass by Reference".
Danke. Habe mir das ganze mal an folgendem Beispiel angeschaut:
Das Ergebnis dieses Scriptes lautet: 3 6 8 10
Was wird gemacht?
Das array @a wird durch \@a als Referenz dargestellt, so dass @a über einen "Zeiger/eine bestimmte Speicheradresse" angesprochen werden kann.
Diese ganzen "Speicheradressen/Zeiger werden dann in der Funktion in der Standardvariablen @_ gespeichert.
Für jede "Speicheradresse/Zeiger" in diesem Array wird dann über die foreach-Schleife ein bestimmter Wert in das neue Array @retlist gespeichert. Der Wert, der in das Array @retlist gespeichert werden soll, wird mit pop aus dem @$aref genommen (So wird über die Speicheradresse/Zeiger auf den Inhalt des eigentlichen Arrays zugegriffen).
Es werden so alle angegebenen Arrays/Arrayreferenzen durchlaufen.
Habe ich das ganze nun endlich richtig verstanden?
Hoffe, man kann meiner Erklärung folgen
Code: Alles auswählen
@a=(1,2,3);
@b=(4,5,6);
@c=(7,8);
@d=(9,10);
@tailings = popmany ( \@a, \@b, \@c, \@d );
sub popmany {
my $aref;
my @retlist = ();
foreach $aref ( @_ ) {
push @retlist, pop @$aref;
}
return @retlist;
}
print "@tailings\n";
Was wird gemacht?
Das array @a wird durch \@a als Referenz dargestellt, so dass @a über einen "Zeiger/eine bestimmte Speicheradresse" angesprochen werden kann.
Diese ganzen "Speicheradressen/Zeiger werden dann in der Funktion in der Standardvariablen @_ gespeichert.
Für jede "Speicheradresse/Zeiger" in diesem Array wird dann über die foreach-Schleife ein bestimmter Wert in das neue Array @retlist gespeichert. Der Wert, der in das Array @retlist gespeichert werden soll, wird mit pop aus dem @$aref genommen (So wird über die Speicheradresse/Zeiger auf den Inhalt des eigentlichen Arrays zugegriffen).
Es werden so alle angegebenen Arrays/Arrayreferenzen durchlaufen.
Habe ich das ganze nun endlich richtig verstanden?
Hoffe, man kann meiner Erklärung folgen
Oh, yeah!
Jo, das hoert sich denke ich ganz ok an.
Innerhalb von popmany() sieht @_ so aus: :
Bei jedem Durchlauf der foreach-Schleife holt sich das Skript eine der 3 Referenzen:
1. [1,2,3]
2. [4,5,6]
3. [7,8]
4. [9,10]
Die push-Zeile derefenziert dann $aref mittels @$aref um mittels pop den letzten Wert aus dem Array zu holen:
1. 3
2. 6
3. 8
4. 10
Diese Werte werden in der obigen Reihenfolge dann in @retlist abgelegt:
und dieser Array wird dann zurueckgegeben.
Innerhalb von popmany() sieht @_ so aus: :
Code: Alles auswählen
[[1,2,3],[4,5,6],[7,8],[9,10]]
1. [1,2,3]
2. [4,5,6]
3. [7,8]
4. [9,10]
Die push-Zeile derefenziert dann $aref mittels @$aref um mittels pop den letzten Wert aus dem Array zu holen:
1. 3
2. 6
3. 8
4. 10
Diese Werte werden in der obigen Reihenfolge dann in @retlist abgelegt:
Code: Alles auswählen
[3,6,8,10]