• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Bash string global substitution

}-Tux-{

Hacker
uhelp schrieb:
Es ist zwar richtig, dass ein shopt -s extglob einschaltet und man dann die extended globs verwenden kann.

Nur ändert das Nullkommanix an dieser Parameterexpansion.

Welche Parameterexpansion meinst du?
"Kompaktere" Version, welches obiges Problem (3. Beitrag) loest (extglob wird weiterhin benoetigt):
Code:
S="abc <foo> def <bar>"
echo ${S//<+([!>])>/<XXX>}

}-Tux-{
 

uhelp

Member
Da hast du recht.
Hab das nachgelesen. Lag ich falsch, habe meinen Post angepasst.

extglob bezieht sich auf das Patternmatching. Egal, ob in Filenameexpansion oder sonstwo.
(Der Matching Operator =~ bleibt davon unberührt, weil er immer die PCRE (und somit implizit extglob) verwendet)

Parameter Expansion wird letztlich jede Expansion von Variablen genannt. Also das Ersetzen des ${someVar} Konstruktes mit dem resultierenden Wert aus dem Inhalt der Variablen UND den evtl. innerhalb der Klammern angegebenen Modifikatoren (Search&Replace, Delete, set Default, Indirection, usw.)
 

}-Tux-{

Hacker
uhelp schrieb:
extglob bezieht sich auf das Patternmatching. Egal, ob in Filenameexpansion oder sonstwo.
extglob bezieht sich erstmal nur auf das Pattern Matching waehrend der
Pathname Expansion.

uhelp schrieb:
(Der Matching Operator =~ bleibt davon unberührt, weil er immer die PCRE (und somit implizit extglob) verwendet)
Du meinst vermutlich "==" bzw. "=" (im Kontext von [[ ... ]] ). "=~" erwartet
einen "echten" extended regex (im Kontext von [[ ... ]] ).

}-Tux-{
 

uhelp

Member
Nein, ich meinte schon den Matching Operator.

Und ja, wie ich oben ja auch geschrieben habe, kommt da ein echter RegEx.
Das war ungeschickt von mir formuliert.

Aber die Parameter Expansion findet dennoch statt:
Code:
s='abciadefgh'
re='([ad])'
if [[ $s =~ ${re//d/} ]]; then
   :
fi
for m in ${BASH_REMATCH[@]}; do
   echo $m
done
Das macht zwar wirklich keinen Sinn mehr, aber es passiert dennoch.
 
OP
Gräfin Klara

Gräfin Klara

Hacker
}-Tux-{ schrieb:
Gräfin Klara schrieb:
RegEx-Engine einstellen:
# shopt -s extglob
ändert nichts für bash intener, eigener regexp
Damit stehen dir die "extended pattern matching operators" zur Verfuegung.
Code:
S="abc <foo> def <bar>"
while test "$S" != "${S/<+([!>])>/XXX}"; do
  S="${S/<+([!>])>/XXX}";
done
echo $S
Liefert "abc XXX def XXX" (geht bestimmt auch eleganter...).


}-Tux-{



Solche Lösungen gibt es haufenweise, es ist jedoch nicht die gesuchte. global substitution, so steht es in der Überschrift.
Mit sed sieht die Lösung folgend aus:
Code:
STR="A:<> B:<x> C:<xy>"
echo "$(sed s/\<[\-A-Za-z0-9]*\>/\<Hallo\>/g <<< $STR)"
Das ist mit bash und ihrer eingebauten regex (// für global) nicht lösbar, weil nach 20 Jahren bash noch immer keine precedings * und ? und dots zur Verfügung stehen. Anstatt diese alte regex aus der bash zu entfernen und das Posix library einzubinden, wird weiter dieser inkompatible Kram gepflegt.
Bash ist Ramsch, dabei bleibt's

Gruß
Gräfin Klara
 

marce

Guru
Nur weil man mit einem Hammer keine Schraube eindrehen kann ist der Hammer kein Ramsch.
Und nur, weil evtl. Dein Problem mit Bash-Internas nicht lösbar ist ist die Bash auch kein Ramsch.

Die Bash macht seit Jahrzehnten das, was sie soll mehr als gut. Und noch vieles mehr.
 

uhelp

Member
Aus dem Gesagten hätte längst klar sein könnnen,
dass das natürlich trotzdem geht.

Schon seit Jahrzehnten.
Code:
shopt -s extglob

STR="A:<> B:<x> C:<xy>"
SBS="Hallo"

echo "$STR"
echo ${STR//<*([[:alnum:]])>/<$SBS>}
*(PATTERN) ist das Syntaxkonstrukt, das dir entgangen ist. Es wurde aber schon genannt.
Die Bash ist kein Ramsch.
Ramsch ist immer nur das zu geringe Wissen der Looser, pardon: der User.

Entschuldigen Sie bitte, meine Unfähigkeit Ihr Ziel sofort zu weissagen.
 
OP
Gräfin Klara

Gräfin Klara

Hacker
uhelp schrieb:
Aus dem Gesagten hätte längst klar sein könnnen,
dass das natürlich trotzdem geht.

Schon seit Jahrzehnten.
Code:
shopt -s extglob

STR="A:<> B:<x> C:<xy>"
SBS="Hallo"

echo "$STR"
echo ${STR//<*([[:alnum:]])>/<$SBS>}
*(PATTERN) ist das Syntaxkonstrukt, das dir entgangen ist. Es wurde aber schon genannt.
Die Bash ist kein Ramsch.
Ramsch ist immer nur das zu geringe Wissen der Looser, pardon: der User.

Entschuldigen Sie bitte, meine Unfähigkeit Ihr Ziel sofort zu weissagen.

Ich habe schon am Anfang darauf hingewiesen,
http://linux-club.de/forum/viewtopic.php?f=91&t=121334&sid=4afdf70fdaaa866ded1877238bc88657#p775245
dass das buildin
# shopt -s extglob
für extended patterns nicht funktioniert

Leseschwäche?
 

uhelp

Member
Und deshalb tut mein Beispiel?

Bei mir funktioniert das einwandfrei.

Und wenn du den Code nur einmal versuchen würdest,
wüßtest du auch, dass shopt -s|-u extglob sehr wohl funktioniert.
Einmal mit -s einmal mit -u probiert zeigt das mehr als deutlich.
 
Oben