Shell-Code in Systemaufrufen und use warnings

Hallo,

ich habe in einem Perl-Skript folgende Zeilen:

my $ziplist_command = "unzip -l";
my $zip_sedcommand = "sed -e 's [at] [^[:alpha:]/]* [at] [at] '";
my $zip_egrepcommand = "egrep -v '^$|^files'";

-f $lw35nfss or
system($ziplist_command $lw35nfss_archive | $zip_sedcommand | $zip_egrepcommand > $lw35nfss);

Zunächst hatte ich die sed- und grep-Aufrufe einfach in der system-Zeile
stehen. Jetzt sind sie brav gequotet in einer Variablen, aber trotzdem
beschwert sich "use warnings;":

Possible unintended interpolation of [at] ' in string at /home/frank/bin/searchbase35 line 15.
Possible precedence problem on bitwise | operator at /home/frank/bin/searchbase35 line 19.

(In Zeile 15 wird $zip_sedcommand definiert, in 19 steht der
Systemaufruf).

Natürlich könnte ich das alles auch in Perl realisieren: Die Ausgabe
von "unzip -l" in eine Variable speichern, reguläre Ausdrücke darauf
anwenden, in eine Datei schreiben. Aber eigentlich wollte ich nur die
Teile eines Shell-Skripts, die in Shell unübersichtlich oder ineffizient
sind, in Perl umschreiben und erweitern. Diese Zeile finde ich
allerdings so viel lesbarer (eigentlich hätte ich am liebsten die sed-
und egrep-Befehle direkt im System-Aufruf), und kürzer wird sie wohl
auch sein.

Jetzt brauche ich natürlich doch länger, weil ich wissen will, wie man
das richtig macht...


TIA, Frank


(ob es überhaupt funktioniert weiß ich noch gar nicht...)
--
> Ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
"kaffee" war es nicht.
frank [ Di, 06 Juni 2006 21:29 ] [ ID #1344587 ]

Re: Shell-Code in Systemaufrufen und use warnings

Frank Küster schrieb:
> Hallo,
>
> ich habe in einem Perl-Skript folgende Zeilen:
>
> my $zip_sedcommand = "sed -e 's [at] [^[:alpha:]/]* [at] [at] '";
>
> Possible unintended interpolation of [at] ' in string at /home/frank/bin/searchbase35 line 15.
>
> (In Zeile 15 wird $zip_sedcommand definiert, in 19 steht der
> Systemaufruf).

Du hast hier ja einen String in Doublequotes. In diesen wird [at] array
interpoliert.

Also zum Beispiel:
[at] x=qw(a b);
$x="test [at] x";
print $x;

Du solltest daher einfache Quotes verwenden. Da du aber auch das
'-Zeichen im String hast, empfehle ich dir, den q-Operator zu nutzen.

Also:
$zip_sedcommand = q(sed -e 's [at] [^[:alpha:]/]* [at] [at] ');

Wolf
Wolf Behrenhoff [ Di, 06 Juni 2006 22:04 ] [ ID #1344588 ]

Re: Shell-Code in Systemaufrufen und use warnings

Frank Küster <frank [at] kuesterei.ch> wrote:
> ich habe in einem Perl-Skript folgende Zeilen:
>
> my $ziplist_command = "unzip -l";
> my $zip_sedcommand = "sed -e 's [at] [^[:alpha:]/]* [at] [at] '";
> my $zip_egrepcommand = "egrep -v '^$|^files'";
>
> -f $lw35nfss or
> system($ziplist_command $lw35nfss_archive | $zip_sedcommand | $zip_egrepcommand > $lw35nfss);
[..]
> Natürlich könnte ich das alles auch in Perl realisieren: Die Ausgabe
> von "unzip -l" in eine Variable speichern, reguläre Ausdrücke darauf
> anwenden, in eine Datei schreiben.

Das waere besser. Suchst du evtl. sowas:

====
#!/usr/bin/perl -w
use strict;
use Archive::Zip qw(:ERROR_CODES);

my $lw35nfss_archive = "/tex-archive/macros/latex/required/psnfss/lw35nfss.zip";
my $lw35nfss = "/dev/stdout";

if( ! -f $lw35nfss ) {
my $uz = new Archive::Zip or die;
$uz->read($lw35nfss_archive) == AZ_OK or die;
open(OUT, '>', $lw35nfss) or die "$!\n";
print OUT join("\n", $uz->memberNames()), "\n";
close(OUT) or die "$!\n";
}
====

Damit sparst du dir das parsen der 'unzip -l'-Ausgabe komplett.

Aber, der Vollstaendigkeit halber:

==== Beginn wie oben ====
if( ! -f $lw35nfss ) {
open(UZ, "unzip -l $lw35nfss_archive |") or die "$!\n";
open(OUT, '>', $lw35nfss) or die "$!\n";
print OUT join("\n",
grep { s [at] [^[:alpha:]/.]* [at] [at] g; !/^$|^files/; } <UZ>
), "\n";
close(OUT) or die "$!\n";
close(UZ) or die "$!\n";
}
====

-dnh

--
180: Roxen
Ein aufgemotztes Shellscript, das sich für einen Webserver hält
und nach einem explodierten Space-Shuttle benannt ist.
(Kristian Köhntopp)
David Haller [ Di, 06 Juni 2006 23:12 ] [ ID #1346441 ]

Re: Shell-Code in Systemaufrufen und use warnings

Wolf Behrenhoff <NoSpamPleaseButThisIsValid3 [at] gmx.net> wrote:

> Du solltest daher einfache Quotes verwenden. Da du aber auch das
> '-Zeichen im String hast, empfehle ich dir, den q-Operator zu nutzen.
>
> Also:
> $zip_sedcommand = q(sed -e 's [at] [^[:alpha:]/]* [at] [at] ');

Ja, dankeschön. Mittlerweile habe ich das auch durch ausprobieren
rausgefunden...

Gruß, Frank
--
> ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
"kaffee" war es nicht.
frank [ Mi, 07 Juni 2006 09:31 ] [ ID #1346444 ]

Re: Shell-Code in Systemaufrufen und use warnings

David Haller <dhaller [at] spamgourmet.com> wrote:

> Frank Küster <frank [at] kuesterei.ch> wrote:
>> ich habe in einem Perl-Skript folgende Zeilen:
>>
>> my $ziplist_command = "unzip -l";
>> my $zip_sedcommand = "sed -e 's [at] [^[:alpha:]/]* [at] [at] '";
>> my $zip_egrepcommand = "egrep -v '^$|^files'";
>>
>> -f $lw35nfss or
>> system($ziplist_command $lw35nfss_archive | $zip_sedcommand | $zip_egrepcommand > $lw35nfss);
> [..]
>> Natürlich könnte ich das alles auch in Perl realisieren: Die Ausgabe
>> von "unzip -l" in eine Variable speichern, reguläre Ausdrücke darauf
>> anwenden, in eine Datei schreiben.
>
> Das waere besser. Suchst du evtl. sowas:
>
> ====
> #!/usr/bin/perl -w
> use strict;
> use Archive::Zip qw(:ERROR_CODES);
>
> my $lw35nfss_archive = "/tex-archive/macros/latex/required/psnfss/lw35nfss.zip";
> my $lw35nfss = "/dev/stdout";
>
> if( ! -f $lw35nfss ) {
> my $uz = new Archive::Zip or die;
> $uz->read($lw35nfss_archive) == AZ_OK or die;
> open(OUT, '>', $lw35nfss) or die "$!\n";
> print OUT join("\n", $uz->memberNames()), "\n";
> close(OUT) or die "$!\n";
> }
>
> ====
> Damit sparst du dir das parsen der 'unzip -l'-Ausgabe komplett.

Nein, sowas suche ich nicht. Zum Beispiel weil Archive::Tar eine andere
Syntax hat, und ich noch gar nicht weiß, welche anderen Archive genauso
bearbeitet werden sollen. Zweck des "Projektes" ist nicht, möglichst
viele Module zum Bearbeiten verschiedener Archive kennenzulernen...

> Aber, der Vollstaendigkeit halber:
>
> ==== Beginn wie oben ====
> if( ! -f $lw35nfss ) {
> open(UZ, "unzip -l $lw35nfss_archive |") or die "$!\n";
> open(OUT, '>', $lw35nfss) or die "$!\n";
> print OUT join("\n",
> grep { s [at] [^[:alpha:]/.]* [at] [at] g; !/^$|^files/; } <UZ>
> ), "\n";
> close(OUT) or die "$!\n";
> close(UZ) or die "$!\n";
> }

Wollte ich das anwenden, müsste ich mich nun in die Doku vertiefen, um
zu verstehen, warum das Perl-grep die Option g braucht. Sonst fällt mir
das irgendwann auf die Füsse.

Gruß, Frank
--
> ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
"kaffee" war es nicht.
frank [ Mi, 07 Juni 2006 12:58 ] [ ID #1346446 ]

Re: Shell-Code in Systemaufrufen und use warnings

Frank Küster <frank [at] kuesterei.ch> wrote:

>>> Natürlich könnte ich das alles auch in Perl realisieren: Die Ausgabe
>>> von "unzip -l" in eine Variable speichern, reguläre Ausdrücke darauf
>>> anwenden, in eine Datei schreiben.
>>
>> Das waere besser. Suchst du evtl. sowas:
[...]
> Nein, sowas suche ich nicht.

Vielleicht doch, denn jetzt sehe ich, dass ich die Dateiliste auch im
Perlscript weiterverarbeiten muss...

Gruß, Frank
--
> ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
"kaffee" war es nicht.
frank [ Mi, 07 Juni 2006 13:50 ] [ ID #1346447 ]

Re: Shell-Code in Systemaufrufen und use warnings

Frank Küster <frank [at] kuesterei.ch> writes:

[...]
> Nein, sowas suche ich nicht. Zum Beispiel weil Archive::Tar eine andere
> Syntax hat, und ich noch gar nicht weiß, welche anderen Archive genauso
> bearbeitet werden sollen. Zweck des "Projektes" ist nicht, möglichst
> viele Module zum Bearbeiten verschiedener Archive kennenzulernen...

Dann könnte Archive::Any etwas für dich sein. Disclaimer: ich habe es
noch nie verwendet, aber die Manpage sieht vielversprechend aus.

Gruß,
Slaven

--
Slaven Rezic - slaven <at> rezic <dot> de

tknotes - A knotes clone, written in Perl/Tk.
http://ptktools.sourceforge.net/#tknotes
Slaven Rezic [ Mi, 07 Juni 2006 20:57 ] [ ID #1346451 ]

Re: Shell-Code in Systemaufrufen und use warnings

Frank Küster <frank [at] kuesterei.ch> wrote:
> David Haller <dhaller [at] spamgourmet.com> wrote:
[..]
>> Damit sparst du dir das parsen der 'unzip -l'-Ausgabe komplett.
>
> Nein, sowas suche ich nicht. Zum Beispiel weil Archive::Tar eine andere
> Syntax hat, und ich noch gar nicht weiß, welche anderen Archive genauso
> bearbeitet werden sollen. Zweck des "Projektes" ist nicht, möglichst
> viele Module zum Bearbeiten verschiedener Archive kennenzulernen...

Ist es besser stattdessen die unterschiedlichen Ausgaben von anderen
(Ent-)Packern zu parsen? Die dann auch installiert sein muessen?

IMHO nicht.

>> Aber, der Vollstaendigkeit halber:
>>
>> ==== Beginn wie oben ====
>> if( ! -f $lw35nfss ) {
>> open(UZ, "unzip -l $lw35nfss_archive |") or die "$!\n";
>> open(OUT, '>', $lw35nfss) or die "$!\n";
>> print OUT join("\n",
>> grep { s [at] [^[:alpha:]/.]* [at] [at] g; !/^$|^files/; } <UZ>
>> ), "\n";
>> close(OUT) or die "$!\n";
>> close(UZ) or die "$!\n";
>> }
>
> Wollte ich das anwenden, müsste ich mich nun in die Doku vertiefen, um
> zu verstehen, warum das Perl-grep die Option g braucht. Sonst fällt mir
> das irgendwann auf die Füsse.

Das ist nicht das 'grep' sondern der s///-Befehl. Und es wird wohl
auch nicht gebraucht. Obiges ist ja die 'grep BLOCK LIST'
Variante. Und im Block tauchen eben ein s/// und ein ! m// auf.

-dnh

--
4: Garbage Collection
Windows 95 (Kristian Köhntopp)
David Haller [ Mi, 07 Juni 2006 20:32 ] [ ID #1346461 ]

Re: Shell-Code in Systemaufrufen und use warnings

David Haller <dhaller [at] spamgourmet.com> wrote:

> Frank Küster <frank [at] kuesterei.ch> wrote:
>> David Haller <dhaller [at] spamgourmet.com> wrote:
> [..]
>>> Damit sparst du dir das parsen der 'unzip -l'-Ausgabe komplett.
>>
>> Nein, sowas suche ich nicht. Zum Beispiel weil Archive::Tar eine andere
>> Syntax hat, und ich noch gar nicht weiß, welche anderen Archive genauso
>> bearbeitet werden sollen. Zweck des "Projektes" ist nicht, möglichst
>> viele Module zum Bearbeiten verschiedener Archive kennenzulernen...
>
> Ist es besser stattdessen die unterschiedlichen Ausgaben von anderen
> (Ent-)Packern zu parsen? Die dann auch installiert sein muessen?

Installiert sind sie sowieso - Es geht ja hier darum, ein existierendes
Shellskript, das den Anforderungen nicht mehr gewachsen ist, in ein
nettes Perlskript umzubauen. Da halte ich es schon für sinnvoll, erst
mal nur die Dinge zu verändern, die verändert werden müssen.

Allerdings - wie ich anderswo schon schrieb - wurde mir dann bewusst,
dass einer der Limitierungen des Shellskripts am einfachsten dadurch
abgeholfen werden kann, dass man die Dateiliste aller Archive im
Speicher hält. Also brauche ich gar keine externe Datei, und damit ist
natürlich eine reine Perl-Lösung angesagt.

>>> Aber, der Vollstaendigkeit halber:
>>>
>>> ==== Beginn wie oben ====
>>> if( ! -f $lw35nfss ) {
>>> open(UZ, "unzip -l $lw35nfss_archive |") or die "$!\n";
>>> open(OUT, '>', $lw35nfss) or die "$!\n";
>>> print OUT join("\n",
>>> grep { s [at] [^[:alpha:]/.]* [at] [at] g; !/^$|^files/; } <UZ>
>>> ), "\n";
>>> close(OUT) or die "$!\n";
>>> close(UZ) or die "$!\n";
>>> }
>>
>> Wollte ich das anwenden, müsste ich mich nun in die Doku vertiefen, um
>> zu verstehen, warum das Perl-grep die Option g braucht. Sonst fällt mir
>> das irgendwann auf die Füsse.
>
> Das ist nicht das 'grep' sondern der s///-Befehl. Und es wird wohl
> auch nicht gebraucht. Obiges ist ja die 'grep BLOCK LIST'
> Variante. Und im Block tauchen eben ein s/// und ein ! m// auf.

Ach so, ich dachte die Veränderung wäre extra geschehen.

Gruß, Frank
--
> ich wusste mal einen Befehl, der die Ausgabe auf stdout noch zusätzlich
> in eine Datei umlenken konnte... Bitte helft mir auf die Sprünge.
"kaffee" war es nicht.
frank [ Do, 08 Juni 2006 09:28 ] [ ID #1348223 ]
Perl » de.comp.lang.perl.misc » Shell-Code in Systemaufrufen und use warnings

Vorheriges Thema: String mit Tabulatoren: Wie richtig alignen?
Nächstes Thema: Perl-Threads, Variablen teilen