
Wie kann ich in einem bash
Skript ein Wort aus einer Zeichenfolge entfernen? Das Wort würde in einer Variablen gespeichert.
FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"
Antwort1
Verwenden bash
der Teilzeichenfolgenersetzung (kopiert aus ksh93):
FOO=${FOO//"$WORDTOREMOVE"/}
Das //
ersetzt alle Vorkommen der Teilzeichenfolge ( $WORDTOREMOVE
) durch den Inhalt zwischen /
und }
. In diesem Fall nichts.
Beachten Sie die Anführungszeichen, $WORDTOREMOVE
um sicherzustellen, dass der Inhalt als feste Zeichenfolge und nicht als Muster verstanden wird.
Wenn der Ersatz leer ist, /
kann das auch weggelassen werden: ${FOO//"$WORDTOREMOVE"}
.
Informationen hierzu und zu anderen Möglichkeiten, mit Strings in Bash zu arbeiten, finden Sie im Abschnitt10.1. Manipulation von ZeichenkettendesErweitertes Bash-Scripting-Handbuch.
Antwort2
Versuchen:
$ printf '%s\n' "${FOO//"$WORDTOREMOVE"/}"
CATS DOGS FISH
Dies funktioniert auch in ksh93
(woher es kommt) mksh
und zsh
.
POSIXly:
FOO="CATS DOGS FISH MICE"
WORDTOREMOVE="MICE"
remove_word() (
set -f
IFS=' '
s=$1
w=$2
set -- $1
for arg do
shift
[ "$arg" = "$w" ] && continue
set -- "$@" "$arg"
done
printf '%s\n' "$*"
)
remove_word "$FOO" "$WORDTOREMOVE"
Es geht davon aus, dass Ihre Wörter durch Leerzeichen getrennt sind, und hat den Nebeneffekt, dass die Leerzeichen davor und danach entfernt werden "$WORDTOREMOVE"
.
Antwort3
Sie könnensed
so was:
echo $FOO | sed s/"$WORDTOREMOVE"//
Antwort4
Entfernen einesWortaus einer Zeichenfolge, die eine durch Leerzeichen getrennte Liste von Wörtern darstellt, ist nicht so einfach, da Sie entscheiden müssen, was mit dem Abstand auf jeder Seite geschehen soll.
Selbst bei einer vereinfachten Darstellung, bei der zwischen den Wörtern immer ein einzelnes Leerzeichen steht, muss man zwischen mehreren Fällen unterscheiden:
- Wort in der Mitte:
foo MICE bar
->foo bar
: Wort und die Leerzeichen davor und die Leerzeichen danach durch ein einzelnes Leerzeichen ersetzt.${var/+( )MICE+( )/ }
- Wort am Anfang:
MICE foo bar
->foo bar
: Wort und die Leerzeichen danach durch nichts ersetzt:${var/MICE+( )}
- Wort am Ende:
foo bar MICE
->foo bar
: Wort und die Leerzeichen davor durch nichts ersetzt:${var/+( )MICE}
. - dann gibt es das Problem, dass das Wort „where“ bei mehreren aufeinanderfolgenden Vorkommen
${var// MICE / }
nicht funktionieren würdefoo MICE MICE bar
, da die erste Ersetzung den Platz vor dem zweiten „MICE“ beanspruchen würde.
(oben mit dem ${var/pattern/replacement}
Operator aus ksh93).
Einfacher wird es allerdings, wenn Sie vor der Ersetzung am Anfang und am Ende ein Leerzeichen hinzufügen und diese anschließend wieder entfernen, da Sie dann alle Bereiche mit einem einzigen Ersetzungsoperator abdecken können:
var='MICE foo MICE MICE bar MICE'
word=MICE
var=" $var "
var=${var//+(+([[:space:]])"$word")+([[:space:]])/ }
var=${var# } var=${var% }
Sie müssten shopt -s extglob
in Bash oder set -o kshglob
Zsh vorher den KSH88-Operator unterstützen, +([[:space:]])
um ein oder mehrere Leerzeichen abzugleichen.
Oder verwenden Sie zsh
das eigene extendedglob
s( set -o extendedglob
), wo aus ksh +(x)
Folgendes wird x##
:
var=${var//([[:space:]]##$word)##[[:space:]]##/ }
Es ist sogar möglich, den Abstand wiederherzustellen, der nach oder vor den Wörtern war (in zsh
; ksh93 hätte etwas Entsprechendes, bash nicht):
var='MICE foo MICE MICE bar MICE'
word=MICE
set -o extendedglob
var=" $var "
var=${var//(#b)([[:space:]]##$word)##([[:space:]]##)/$match[2]}
var=${var# } var=${var% }
Wenn Sie statt einer Skalarvariablen, die eine Darstellung einer Liste enthält, eine tatsächlicheListe(Array-)Variable, wie in:
var=(MICE foo MICE MICE bar MICE)
Dann reduziert sich das Problem auf das Entfernen bestimmter Elemente aus dem Array, was mit Shells mit richtigen Array-Variablen wie zsh
(woher diese var=(foo bar)
Syntax kommt) trivial wird:
var=( ${var:#$word} )