Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sed: letztes Auftreten eines Zeichens in Datei

344 views
Skip to first unread message

Ralph Stahl

unread,
Jan 23, 2013, 4:46:02 AM1/23/13
to
Moin!

Folgende Aufgabe steht:

Eine Datei enthᅵlt mehrere Zeichenketten '?>'. Falls die in der letzten
Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
es gegen nichts '' ersetzt werden.

(Der Zweck: PHP-Dateien sollten kein schlieᅵendes PHP-Tag am Ende haben.
In einigen meiner alten groᅵen Projekte haben sie das aber alle,
deswegen mᅵchte ich das ᅵber ein Script bereinigen.)

Das Problem: in einem File einfach nur sowas wie

sed 's/\?>\s*$//'

zu machen, geht schief. Dabei werden alle Vorkommen mittendrin mit
gelᅵscht, die aber erhalten bleiben sollen. Weil sed zeilenweise
arbeitet und es kein Kriterium fᅵr "letzte Zeile" gibt (EOF ist kein
testbares Zeichen).

Mᅵglicher Ansatz:

Bekomme ich sed mit einer "Hilfskonstruktion" drumrum irgendwie dazu,
eine Datei (besser: alle Dateien im Verzeichnis) quasi von hinten
aufzurollen und somit die nun ersten Zeilen, die nur /\s*/ oder
/\s*\?>\s*/ enthalten, gᅵnzlich lᅵschen zu kᅵnnen?

Ich wᅵre fᅵr Tips dankbar.
Ralph

Dirk Thierbach

unread,
Jan 23, 2013, 7:04:16 AM1/23/13
to
Ralph Stahl <po...@rstahl.de> wrote:
> Eine Datei enthält mehrere Zeichenketten '?>'. Falls die in der letzten
> Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
> es gegen nichts '' ersetzt werden.

> Ich wäre für Tips dankbar.

Muss es sed sein? IIRC arbeitet das immer zeilenweise, aber Du willst
ja gegen "nur folgende Leerzeichen oder LF, dann Dateiende" matchen.

Warum nicht

perl -pi -e 's/\?\>\s*$//s' dateinamen

oder so etwas (nicht getestet, enthaelt mit Sicherheit Fehler)?

- Dirk


Ralph Stahl

unread,
Jan 23, 2013, 7:27:07 AM1/23/13
to
Dirk Thierbach schrieb:
> Ralph Stahl <po...@rstahl.de> wrote:
>> Eine Datei enthᅵlt mehrere Zeichenketten '?>'. Falls die in der letzten
>> Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
>> es gegen nichts '' ersetzt werden.
>
>> Ich wᅵre fᅵr Tips dankbar.
>
> Muss es sed sein? IIRC arbeitet das immer zeilenweise, aber Du willst
> ja gegen "nur folgende Leerzeichen oder LF, dann Dateiende" matchen.
>
> Warum nicht
>
> perl -pi -e 's/\?\>\s*$//s' dateinamen
>
> oder so etwas (nicht getestet, enthaelt mit Sicherheit Fehler)?
>

sed war nur die erste Idee, perl ist natᅵrlich a) flexibler und b) hier
sicher richtig. So wie es hier steht, macht es leider erstmal genau gar
nichts, obwohl es mir vom regex her richtig scheint. Sag mal, was macht
das s ganz hinten (hab ich vergessen, sorry)?

Wir kommen der Sache nᅵher :-).


Dirk Thierbach

unread,
Jan 23, 2013, 8:38:33 AM1/23/13
to
Ralph Stahl <po...@rstahl.de> wrote:

> Sag mal, was macht das s ganz hinten (hab ich vergessen, sorry)?

Schaltet die zeilenweise Verarbeitung ab. Es kann sein, dass
"-pi" aber trotzdem zeilenweise arbeitet. Wie gesagt, ich habe nicht
lange drueber nachgedacht. man perlrun, man perlre.

- Dirk

Henning Paul

unread,
Jan 23, 2013, 9:36:18 AM1/23/13
to
Ralph Stahl schrieb:

> Das Problem: in einem File einfach nur sowas wie
>
> sed 's/\?>\s*$//'
>
> zu machen, geht schief. Dabei werden alle Vorkommen mittendrin mit
> gelöscht, die aber erhalten bleiben sollen. Weil sed zeilenweise
> arbeitet und es kein Kriterium für "letzte Zeile" gibt (EOF ist kein
> testbares Zeichen).

sed kennt aber Adressen und Ranges.

sed '$ s/\?>\s*$//'

arbeitet nur auf der letzten Zeile.

Gruß
Henning

Christoph 'Mehdorn' Weber

unread,
Jan 23, 2013, 9:56:19 AM1/23/13
to
Hallo!

* Ralph Stahl <po...@rstahl.de>:

> Eine Datei enthᅵlt mehrere Zeichenketten '?>'. Falls die in der letzten
> Zeile steht

Fᅵr diesen Fall gibt es die Adresse "$": "Match the last line."

Aus

> sed 's/\?>\s*$//'

wird

| sed '$s/\?>\s*$//'

und schon ist die letzte Zeile davon bereinigt. Na ja, eventuell
will man eher "sed -s -i" auf "*.php" anwenden.


> oder nur noch Leerzeilen oder -zeichen danach kommen, soll
> es gegen nichts '' ersetzt werden.

Da wᅵᅵte ich auf Anhieb keine Lᅵsung. Man kann zwar einen
Bereich "/\?>\s*$/,$" benutzen, aber der setzt, soweit ich weiᅵ,
beim ersten Vorkommen von "?>" an.

Man kann derartige Probleme, soweit ich mich erinnere, aber
trotzdem mit sed lᅵsen, aber der Ausdruck ist zu kompliziert,
als daᅵ ich ihn mir gemerkt hᅵtte.


Alternativ schrittweise vorgehen und den ersten Ausdruck so
modifizieren, daᅵ er mehr oder minder leere Zeilen am Ende
entfernt, und wenn das erledigt ist, obigen sed-Aufruf absetzen:

| sed -s -i '$/^\s*$/d' *.php

Haken: Wenn es mehr als eine Leerzeile am Ende ist, muᅵt du es
ggf. mehrfach aufrufen. Und man weiᅵ nicht, ob er wirklich was
entfernt hat, ohne separat nachzugucken.

> Bekomme ich sed mit einer "Hilfskonstruktion" drumrum irgendwie dazu,
> eine Datei (besser: alle Dateien im Verzeichnis) quasi von hinten
> aufzurollen und somit die nun ersten Zeilen, die nur /\s*/ oder
> /\s*\?>\s*/ enthalten, gᅵnzlich lᅵschen zu kᅵnnen?

Zum Umdrehen gibt es "tac".

Christoph

--
In Berlin gibt es die Pfannkuchen sowohl mit Puderzucker als auch mit
Zuckerguss. Beide Arten bekomme ich nur mit Widerwillen herunter. --
"Ein Pfannkuchen mit Puderzucker und Widerwillen, bitte..."
(Dieter Bruegmann, Volker Gringmuth)

Henning Paul

unread,
Jan 23, 2013, 11:08:44 AM1/23/13
to
Christoph 'Mehdorn' Weber schrieb:

> Da wüßte ich auf Anhieb keine Lösung. Man kann zwar einen
> Bereich "/\?>\s*$/,$" benutzen, aber der setzt, soweit ich weiß,
> beim ersten Vorkommen von "?>" an.

sed ist ja auch gierig, "greedy".

> Man kann derartige Probleme, soweit ich mich erinnere, aber
> trotzdem mit sed lösen, aber der Ausdruck ist zu kompliziert,
> als daß ich ihn mir gemerkt hätte.

Der Standardansatz ist in dem Fall, sed auf "Muster, gefolgt von
beliebig vielen Wiederholungen von allem außer Muster" matchen zu
lassen. Muss man sich hinbasteln.

Gruß
Henning

Ralph Stahl

unread,
Jan 23, 2013, 11:38:50 AM1/23/13
to
Henning Paul schrieb:
Aha, interssant!

Ich antworte mal Dir stellvertretend für alle - da sind ja viele schöne
Gedanken gekommen, danke! Muß ich erstmal setzen lassen. Es tröstet
mich, daß es tatsächlich nicht so trivial ist ^^.

Vielleicht so: obiges nur für die letzte Zeile geht (wo '?>' ggf gar
nicht steht)

1) sed '$ s/\?>\s*$//' *.php

und ich kombiniere das mit einem vorhergehenden Konstrukt, das mir
zunächst nur alle \s* am Ende der Datei wegwirft - dann hätte ich als
letzte Zeichen entweder '?>' oder auch nicht. Wenn ja, werfe ich sie weg.

Nach [1] (Zeile 309) könnte das Löschen aller Leerzeilen (ggf mit \s*
vor den \n) so aussehen (nicht getestet undnoch nicht verstanden!):

2) sed -e :a -e '/^\s*\n*$/{$d;N;ba' -e '}' *.php

Also erst 2), dann 1) in einem Script zusammengefaßt. Das lasse ich mir
jetzt mal durch den Kopf gehen und probiere ein bißchen rum.
Abenteuerlich siehts ja schon mal aus ^^. Tja, mein letztes
sed/awk/perl-Erlebnis ist 14 Jahre her, da vergißtman alles...

Also danke erstmal, ich melde mich wieder,
Ralph


[1] http://sed.sourceforge.net/sed1line_de.html
"Nützliche, einzeilige Scripts für SED"

Dirk Thierbach

unread,
Jan 23, 2013, 2:40:57 PM1/23/13
to
Dirk Thierbach <dthie...@usenet.arcornews.de> wrote:
> Schaltet die zeilenweise Verarbeitung ab. Es kann sein, dass
> "-pi" aber trotzdem zeilenweise arbeitet.

Tut es. Also muss man das auch abschalten. Test:

$ echo -e "abc?>\nde?>\n\n\n" | perl -lpe 'BEGIN{$/=""}s/\?\>$//s'
abc?>
de

$ echo -e "abc?>\nde?>f\n\n\n" | perl -lpe 'BEGIN{$/=""}s/\?\>$//s'
abc?>
de?>f

Das wolltest Du doch, oder? -i hinzufuegen, um Dateien "in-place" zu
ersetzen (nicht getestet, ich hoffe, es gibt keine Zusatzkomplikationen.
Sonst halt mit externer Schleife).

- Dirk

Torsten Berger

unread,
Jan 23, 2013, 2:39:55 PM1/23/13
to
Hallo Ralph,

Am 23.01.2013 10:46, schrieb Ralph Stahl:
> Eine Datei enthält mehrere Zeichenketten '?>'. Falls die in der letzten
> Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
> es gegen nichts '' ersetzt werden.

vielleicht hilft Dir ja das kleine bash Script weiter.
Es löscht alles rückwärts aus der eingabedatei inkl. des ersten
Vorkommens von "?>".

--------------schnippel-------------
#!/bin/bash

v="$(<"${1}")"
v="${v%'?>'*}"
echo "$v"
--------------schnippel-------------
also:

script eingabedatei > ausgabedatei

Bye Torsten.

Thomas 'PointedEars' Lahn

unread,
Jan 23, 2013, 5:23:31 PM1/23/13
to
de.comp.os.unix.shell existiert. X-Post & F'up2.

Ralph Stahl wrote:

> Folgende Aufgabe steht:
>
> Eine Datei enthält mehrere Zeichenketten '?>'. Falls die in der letzten
> Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
> es gegen nichts '' ersetzt werden.
>
> (Der Zweck: PHP-Dateien sollten kein schließendes PHP-Tag am Ende haben.

Das wird für neuen Code empfohlen, damit sich nicht nicht-druckbare Zeichen
einschleichen, die z. B. für ein vorzeitiges Ende des HTTP-Headers sorgen.
Notwendig, das bei altem Code zu machen, ist es nicht, wenn dieser
funktioniert. Das Einfachste wäre, alle Zeichen nach dem “?>” zu entfernen.

> In einigen meiner alten großen Projekte haben sie das aber alle,
> deswegen möchte ich das über ein Script bereinigen.)

Nicht sinnvoll.

> Das Problem: in einem File einfach nur sowas wie
>
> sed 's/\?>\s*$//'
>
> zu machen, geht schief. Dabei werden alle Vorkommen mittendrin mit
> gelöscht, die aber erhalten bleiben sollen. Weil sed zeilenweise
> arbeitet und es kein Kriterium für "letzte Zeile" gibt (EOF ist kein
> testbares Zeichen).

Du irrst. Die letzte Zeile hat die Adresse “$”.

> Möglicher Ansatz:
>
> Bekomme ich sed mit einer "Hilfskonstruktion" drumrum irgendwie dazu,
> eine Datei (besser: alle Dateien im Verzeichnis) quasi von hinten
> aufzurollen und somit die nun ersten Zeilen, die nur /\s*/ oder
> /\s*\?>\s*/ enthalten, gänzlich löschen zu können?

Nein. Kanonen, Spatzen.

> Ich wäre für Tips dankbar.

Wenn Du etwas nicht zeilenbasiertes machen willst, suchst Du der Einfachheit
halber kein zeilenbasiertes Tool wie sed. Offensichtlich hast Du PHP; nutz
es:

file_put_contents(
'Foo.php',
preg_replace('/?>\\s*$/', '', file_get_contents('Foo.php')));

Ungetestet. Ähnlich geht es mit Perl.

> Ralph

--
PointedEars

Twitter: @PointedEars2
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

Thomas 'PointedEars' Lahn

unread,
Jan 23, 2013, 5:30:18 PM1/23/13
to
Dirk Thierbach wrote:

> Ralph Stahl <po...@rstahl.de> wrote:
>> Sag mal, was macht das s ganz hinten (hab ich vergessen, sorry)?
>
> Schaltet die zeilenweise Verarbeitung ab.

Nein, es sorgt dafür, dass “.” auch auf Newline matcht. Perl-RE arbeiten
per Default _nicht_ zeilenbasiert, dafür bräuchte man /m. /s ist daher in
einem Ausdruck, der kein “.” enthält, überflüssig. perldoc perlre.

F'up2 de.comp.lang.perl.misc

Thomas 'PointedEars' Lahn

unread,
Jan 23, 2013, 6:42:56 PM1/23/13
to
Dirk Thierbach wrote:

> Dirk Thierbach <dthie...@usenet.arcornews.de> wrote:
>> Schaltet die zeilenweise Verarbeitung ab. Es kann sein, dass
>> "-pi" aber trotzdem zeilenweise arbeitet.
>
> Tut es. Also muss man das auch abschalten. Test:
>
> $ echo -e "abc?>\nde?>\n\n\n" | perl -lpe 'BEGIN{$/=""}s/\?\>$//s'
^
Wie gesagt: /s ist überflüssig, da sich kein “.” im Ausdruck befindet, der
dann auch als Newline interpretiert werden könnte.

> abc?>
> de
>
> $ echo -e "abc?>\nde?>f\n\n\n" | perl -lpe 'BEGIN{$/=""}s/\?\>$//s'
> abc?>
> de?>f
>
> Das wolltest Du doch, oder?

Oder. Es hilft hier natürlich, neben einem Perl- auch einen PHP-Minimalclue
zu haben, durch den man weiss, dass “… abc?>\nde?>f\n\n\n” kein syntaktisch
korrekter PHP-Code sein kann (auch für geeignete Werte von “de” und “f”
nicht), und daher nicht Ziel dieser Übung sein kann.

Vielmehr geht es darum, aus

<?php
foo
?>

den Code

<?php
foo

zu machen, damit nicht ungewollt nicht-druckbare Zeichen ausgegeben werden
(ausserhalb von <?php … ?> gibt der *P*HP *H*ypertext *P*reprocessor
zweckgemäss immer alles aus; wilde print/echo-Experimente wie sie in Perl
AFAIK nötig sind, kann man sich so in PHP sparen).

<http://php.net/manual/>

> -i hinzufuegen, um Dateien "in-place" zu ersetzen (nicht getestet, ich
> hoffe, es gibt keine Zusatzkomplikationen. Sonst halt mit externer
> Schleife).

Dein Ansatz ist grober Unfug; “perldoc perlrun”, “perldoc perlvar”;
angesichts Deiner anderen Perl-“Weisheiten” besser vorher noch “perldoc
perlintro”.

Man will hier gerade *keine* Schleife (“-p”), denn es interessiert nur das
*Ende* der Datei. Das entsprechende Perl-Skript könnte daher so aussehen:

use strict;
use warnings;

# Zeilenende ist nicht mehr Datensatzbegrenzer
$/ = "";

# Ganze Datei auf einmal einlesen (Slurping)
$_ = <>;

# “Problematischen” Quelltext löschen
s/(\s* \?> | \s* <\? (?:php)? )+ \s* $//x;

# Geänderten Dateiinhalt ausgeben
print;

oder auf der Befehlszeile

$ printf '\n?>foo<?php bar ?>\n\n<?php' | perl -e 'use strict; use warnings;
$/ = ""; $_ = <>; s/(\s* \?> | \s* <\? (?:php)? )+ \s* $//x; print;'
?>foo<?php bar

Vermutlich geht es noch kürzer, aber das *funktioniert* immerhin und geht
auch bei grossen Dateien hinreichend schnell. Zu beachten ist aber, dass
beim Slurping die Grösse der verarbeitbaren Datei vermutlich durch den
verfügbaren Speicher begrenzt ist. Wie so oft tauscht man also Speicher-
gegen Laufzeiteffizienz.

Wenn man das nicht will, muss man bei einer Schleife zumindest eine
Fallunterscheidung einbauen, damit man *nur* die letzte Zeile bearbeitet
(aber selbst dann ist nicht sichergestellt, dass die letzte Zeile die zu
suchende Zeichenfolge enthält, daher halte ich das Ersetzen im geschlürften
Dateiinhalt hier für deutlich praktischer).

X-Post & F'up2 de.comp.lang.perl.misc

Ralph Stahl

unread,
Jan 24, 2013, 4:39:54 AM1/24/13
to
Torsten Berger schrieb:
> Hallo Ralph,
>
> Am 23.01.2013 10:46, schrieb Ralph Stahl:
>> Eine Datei enthᅵlt mehrere Zeichenketten '?>'. Falls die in der letzten
>> Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
>> es gegen nichts '' ersetzt werden.
>
> vielleicht hilft Dir ja das kleine bash Script weiter.
> Es lᅵscht alles rᅵckwᅵrts aus der eingabedatei inkl. des ersten
> Vorkommens von "?>".
>
> --------------schnippel-------------
> #!/bin/bash
>
> v="$(<"${1}")"
> v="${v%'?>'*}"
> echo "$v"
> --------------schnippel-------------
> also:
>
> script eingabedatei > ausgabedatei
>
> Bye Torsten.
>

Genial, danke! Ich verstehe zwar Bahnhof, aber es funktioniert :-). Nun
noch ne Schleife ᅵber alle *.php drumrum (das bekomme ich wohl hin),
dann nehm ich's.

Ralph

Thomas 'PointedEars' Lahn

unread,
Jan 24, 2013, 12:26:34 PM1/24/13
to
Torsten Berger wrote:

> Am 23.01.2013 10:46, schrieb Ralph Stahl:
>> Eine Datei enthält mehrere Zeichenketten '?>'. Falls die in der letzten
>> Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
>> es gegen nichts '' ersetzt werden.
>
> vielleicht hilft Dir ja das kleine bash Script weiter.
> Es löscht alles rückwärts aus der eingabedatei inkl. des ersten
> Vorkommens von "?>".
>
> --------------schnippel-------------
> #!/bin/bash
>
> v="$(<"${1}")"
> v="${v%'?>'*}"

Die Anführungszeichen um die Command Substitution “$(…)” bzw. Parameter
Expansion “${…}” liefern hier keinen Mehrwert, verwirren dafür gut:

# Inhalt der mit dem ersten Parameter angegebenen Datei in Variable v
# speichern
v=$(< "$1")

# Am Ende des Werts von v ein Minimum an Zeichen (“%” statt “%%”)
# abschneiden, dem “?>” voranggeht (“?” und “>” sind Spezialzeichen, die
# maskiert werden müssen); Ergebnis wieder v zuweisen.
v=${v%'?>'*}

Vorsicht: Dieser Ansatz entfernt auch sinnvollen Code, der “?>” folgt. Er
wäre daher allenfalls für Klassenbibliotheken geeignet, nicht z. B. für
Includes oder Templates.

> echo "$v"

Nur hier sind die Anführungszeichen nötig, damit Zeilenumbrüche nicht zu
Leerzeichen werden.

> --------------schnippel-------------
> also:
>
> script eingabedatei > ausgabedatei

X-Post & F'up2 de.comp.os.unix.shell

Thomas 'PointedEars' Lahn

unread,
Jan 24, 2013, 12:40:11 PM1/24/13
to
Ralph Stahl wrote:

> Torsten Berger schrieb:
>> Am 23.01.2013 10:46, schrieb Ralph Stahl:
>>> Eine Datei enthält mehrere Zeichenketten '?>'. Falls die in der letzten
>>> Zeile steht oder nur noch Leerzeilen oder -zeichen danach kommen, soll
>>> es gegen nichts '' ersetzt werden.
>>
>> vielleicht hilft Dir ja das kleine bash Script weiter.
>> Es löscht alles rückwärts aus der eingabedatei inkl. des ersten
>> Vorkommens von "?>".
>>
>> --------------schnippel-------------
>> #!/bin/bash
>>
>> v="$(<"${1}")"
>> v="${v%'?>'*}"
>> echo "$v"
>> --------------schnippel-------------
>> also:
>>
>> script eingabedatei > ausgabedatei
>
> Genial, danke! Ich verstehe zwar Bahnhof, aber es funktioniert :-). Nun
> noch ne Schleife über alle *.php drumrum (das bekomme ich wohl hin),
> dann nehm ich's.

Findest Du es nicht etwas riskant und im grösseren Rahmen verantwortungslos,
Code zu verwenden, den Du nicht verstehst?

Ralph Stahl

unread,
Jan 24, 2013, 1:22:37 PM1/24/13
to
Thomas 'PointedEars' Lahn schrieb:

[...]

>>> --------------schnippel-------------
>>> #!/bin/bash
>>>
>>> v="$(<"${1}")"
>>> v="${v%'?>'*}"
>>> echo "$v"
>>> --------------schnippel-------------
>>> also:
>>>
>>> script eingabedatei > ausgabedatei
>>
>> Genial, danke! Ich verstehe zwar Bahnhof, aber es funktioniert :-). Nun
>> noch ne Schleife über alle *.php drumrum (das bekomme ich wohl hin),
>> dann nehm ich's.
>
> Findest Du es nicht etwas riskant und im grösseren Rahmen verantwortungslos,
> Code zu verwenden, den Du nicht verstehst?

Natürlich, deswegen nehme ich es ja auch noch nicht, keine Bange :-).
Verstehen will ich es schon unbedingt, deswegen habe ich ja nachgehakt.
Ich probiere auch die anderen angesprochenen Lösungsansätze, notfalls am
Ende PHP (das verstehe ich nun wirklich).

Ralph


Torsten Berger

unread,
Jan 24, 2013, 3:03:52 PM1/24/13
to
Hallo Thomas,

Am 24.01.2013 18:26, schrieb Thomas 'PointedEars' Lahn:
>> v="$(<"${1}")"
>> v="${v%'?>'*}"
>
> Die Anführungszeichen um die Command Substitution “$(…)”
...stimmt, können weg...

> Expansion “${…}” liefern hier keinen Mehrwert, verwirren dafür gut:
...dann versuche es ohne "" und übergib einen Dateinamen mit Leerzeichen...

> v=$(< "$1")
...so geht's nicht. Außer Du hast eine Eingabedatei, die $1 heißt...

> # Am Ende des Werts von v ein Minimum an Zeichen (“%” statt “%%”)
...wenn Du %% verwendest hört es beim ersten Vorkommen NICHT auf...

> Vorsicht: Dieser Ansatz entfernt auch sinnvollen Code, der “?>” folgt. Er
...kommt hier auf den Einsatzzweck an. Das Script verändert ja nicht die
Originaldateien.

Bye Torsten.

Thomas 'PointedEars' Lahn

unread,
Jan 24, 2013, 3:54:20 PM1/24/13
to
Torsten Berger wrote:

> Am 24.01.2013 18:26, schrieb Thomas 'PointedEars' Lahn:
>>> v="$(<"${1}")"
>>> v="${v%'?>'*}"
>>
>> Die Anführungszeichen um die Command Substitution “$(…)”
> ...stimmt, können weg...
>
>> Expansion “${…}” liefern hier keinen Mehrwert, verwirren dafür gut:
> ...dann versuche es ohne "" und übergib einen Dateinamen mit
> Leerzeichen...

Ich habe mich anscheinend missverständlich ausgedrückt. Die
Anführungszeichen um die *äussere* Parameter Expansion sind überflüssig und
verwirrend. Wie ich weiter unten auch schrieb:

>> v=$(< "$1")
>> [ v=${v%'?>'*} ]
^ ^
> ...so geht's nicht. Außer Du hast eine Eingabedatei, die $1 heißt...

Das funktioniert so in jedem Fall, denn Parameter Expansion wird vor Command
Substitution durchführt.

Du unterliegst anscheinend dem Irrtum, dass Parameter Expansion in sh-
basierten Shells nur durchgeführt werden würde, wenn der Parametername
(hier: 1) in geschweiften Klammern stehe.

Funktional notwendig sind die geschweiften Klammern aber nur dann, wenn der
Referenz ein Zeichen folgt, welches als Teil der Referenz gewertet werden
könnte, z. B. ist “$foobar” nicht dasselbe wie “${foo}bar”. Oder es ist in
der Grammatik definiert, dass bestimmte Zeichen einen Parameternamen
abschliessen: “${12}” ist nicht dasselbe wie “$12”; Letzteres ist nämlich
äquivalent zu “${1}2”.

Alles andere ist eine reine Stilfrage.

>> # Am Ende des Werts von v ein Minimum an Zeichen (“%” statt “%%”)
> ...wenn Du %% verwendest hört es beim ersten Vorkommen NICHT auf...
>
>> Vorsicht: Dieser Ansatz entfernt auch sinnvollen Code, der “?>” folgt.
>> Er

Dein Zitierstil saugt. <http://learn.to/quote>

> ...kommt hier auf den Einsatzzweck an. Das Script verändert ja nicht die
> Originaldateien.

Der Einsatzzweck dieses Programms soll sein (der OP deutete es an, ich hatte
es bereits ausgeführt), PHP-Code so zu kürzen, dass er anschliessend weniger
fehlerträchtig, aber trotzdem *äquivalent* zum Original ist.

Ein Ansatz, der *alle* Zeichen nach dem letzten “?>” entfernt und nicht nur
Whitespace, leistet das nur bedingt, nämlich nur für bestimmte PHP-
Eingabedateien. Das Folgende (was man strukturell in einem PHP-Include oder
-Template vorfinden könnte) ist *auch* syntaktisch korrekter PHP-Code (denn
PHP arbeitet wie ein Präprozessor — daher inzwischen der Name):

<?php foo(); ?> bar

Das ist äquivalent zu

<?php foo(); echo ' bar'; ?>

Mit Deinem Ansatz wird daraus aber

<?php foo();

Und das ist _nicht_ äquivalent zum Original. Was für den OP auch ein
Problem ist, wie er in de.comp.os.unix.shell (dcous) schreibt.

Für bessere Lösungen mit der Shell und Shell-nahen Tools siehe den Thread in
dcous. In jene Newsgroup hatte ich ein F'up2 gesetzt, welches Du ohne
Begründung crosspostenderweise ignoriertest, *obwohl* Dein Thunderbird
17.0.2 standardmässig das F'up2 beachtet. F'up2 dcous erneut gesetzt.

<http://www.liesmal.de/fup2-faq>

Josef Moellers

unread,
Jan 26, 2013, 11:12:54 AM1/26/13
to
On 01/23/2013 10:46 AM, Ralph Stahl wrote:

> Bekomme ich sed mit einer "Hilfskonstruktion" drumrum irgendwie dazu,
> eine Datei (besser: alle Dateien im Verzeichnis) quasi von hinten
> aufzurollen und somit die nun ersten Zeilen, die nur /\s*/ oder
> /\s*\?>\s*/ enthalten, gᅵnzlich lᅵschen zu kᅵnnen?

Kennst Du "tac"? Das ist "cat" rᅵckwᅵrts ;-)

also "tac <Datei> | sed 'substituiere nur das erste Auftreten' | tac >
<NeueDatei>"
Wenn die Datei nicht allzu groᅵ ist, dᅵrfte das gehen. Jetzt frag' aber
bitte nicht, wie Du "sed" dazu bekommen kannst, die Ersetzung nur genau
einmal zu machen!

Josef

Ralph Stahl

unread,
Jan 28, 2013, 3:42:40 AM1/28/13
to
Josef Moellers schrieb:
Ja, das habe ich weiter oben (?) schon gelesen, gute Idee. Mal sehen, ob
sich was draus machen lᅵᅵt, danke!

Ralph
Message has been deleted

Dirk Thierbach

unread,
Jan 30, 2013, 4:36:31 AM1/30/13
to
Wolfgang Klein <klein...@web.de> wrote:
> Ich kriege zwar leider den sed-Ausdruck gerade nicht zusammen, aber was
> spricht dagegen, zuerst alle mehrfachen Zeilenumbrüche, also mehr als
> eine Leerzeile hintereinander, zu entfernen,

Und wie wuerdest Du das tun?

> und dann Leerzeile gefolgt von "?>" am Ende der Datei zu entfernen?

Und was passiert dabei, wenn Du mehrfache Zeilenumbrueche innerhalb
der Datei hast? Ist das das, was passieren soll?

- Dirk
Message has been deleted

Helmut Hullen

unread,
Jan 30, 2013, 9:02:00 AM1/30/13
to
Hallo, Dirk,

Du meintest am 30.01.13:

>> Ich kriege zwar leider den sed-Ausdruck gerade nicht zusammen, aber
>> was spricht dagegen, zuerst alle mehrfachen Zeilenumbrüche, also
>> mehr als eine Leerzeile hintereinander, zu entfernen,

> Und wie wuerdest Du das tun?

------------------ Skript "nocomment" ein --------------------
#! /bin/bash
# räumt Leerzeilen und pure Kommentarzeilen weg
# David Haller, de.comp.os.unix.shell 5.11.2012

test "$1" || {
echo Syntax: $0 Dateiname
exit 1
}

sed '/^[[:space:]]*#/d;/^[[:space:]]*$/d;' "$1"
#


------------------ Skript "nocomment" aus --------------------

Viele Gruesse
Helmut

"Ubuntu" - an African word, meaning "Slackware is too hard for me".

0 new messages