2016-05-30 9 views
0

Ich muss "unbedeutende" Teile eines Namens ersetzen. Dies muss in einem Bash-Skript erfolgen. Dazu muss ich die Mittelwörter "VAN", "DEN", ​​"DE" und "DER" entfernen.

Um dies zu tun, ich bin mit dem Einbau-ersetzen (Problem zu 2 Zeilen reduziert):

line="STIG VAN DE WYNKELE"; 
line=${line//@(' VAN '|' DEN '|' DE '|' DER ')/' '}; 
echo $line; 

Ausgang:

STIG DE WYNKELE 

Erwartete Ausgabe:

STIG WYNKELE 

Es scheint so, als ob das @ (...) eines der mittleren Wörter anpasst, wobei alle Vorkommen dieses einen mittleren Wortes entfernt werden, aber nicht othe rs.

Die Frage: Mache ich etwas falsch in meiner Syntax? Wenn nicht, wie würde ich diese Wörter entfernen? sed benötigt Dateien, während meine Eingabe eine Variable ist und der geänderte Text auch in einer Variablen gespeichert werden soll. ($ Zeile sollte geändert werden)

+1

'sed' Dateien nicht benötigt, es ist ein Stream-Editor. 'foo = $ (echo" $ foo "| sed ...)' ist ein allgemeines Idiom. –

+0

Häufig, aber normalerweise unnötig, wenn '$ foo' kurz ist. – chepner

Antwort

3

bash Rückzieher nicht. Zuerst findet es VAN im Eingabe:

STIG VAN DE WYNKELE 
    ^^^^^| 

(wo | stellt seinen Zeiger während Scannen).

Nach VAN mit ersetzen, haben Sie

STIG DE WYNKELE 
    | 

Sie werden bemerken, dass DE nicht im String an D Start gefunden wird; Der Platz, den Sie gerade eingefügt haben, wird nicht von bash überprüft.

Stattdessen fallen den führenden Raum von jedem Muster und ein Spiel löschen, anstatt sie mit einem Leerzeichen ersetzen:

echo "${line//@('VAN '|'DEN '|'DE '|'DER ')}" 

Natürlich ist das Problem dabei ist, dass Sie jetzt ein Tropfen könnten Übereinstimmung, die am Ende eines Wortes auftritt. Es gibt nicht weg, um das mit einem einzigen Spiel zu vermeiden; stattdessen tun mehrere Ersetzungen in einer Schleife:

for word in VAN DEN DE DER; do 
    line=${line// $word/} 
done 
+0

Dies hat das Problem gelöst und sieht wie der beste Weg aus, es ohne Nebenwirkungen zu tun, danke! – Bertware

+0

Es ist möglich mit einem einzigen Match, aber nur mit Look-arounds (nicht unterstützt in bash). – choroba

0

Sie benötigen keine extglob Muster. Sie können nur Parameter Expansion verwenden:

${line/ */} 

Beispiel:

$ line="STIG VAN DE WYNKELE" 
$ echo ${line/ */} 
STIG WYNKELE 
4

Sie müssen die extglob Option setzen. Entfernen Sie die Anführungszeichen und verschieben Sie das Leerzeichen außerhalb der Alternative. Sie können den Ausdruck verkürzen weiter:

#!/bin/bash 
line="STIG VAN DE DEN DER WYNKELE" 
shopt -s extglob 
line=${line//@(VAN|DE?([NR])) } 
echo "$line" 

Mit einem Doppelklick quotting $ Linie in der letzten Zeile können Sie richtig entfernt ob wurden die Räume.

+0

'Need' ist ein starkes Wort. Imo ist es nicht erforderlich, 'extglob' hier zu verwenden – hek2mgl

+0

@ hek2mgl: Um' @ (... | ...) 'zu verwenden, müssen Sie ... – choroba

+0

Uh Sie sind, habe ich übersehen, dass, weil es ist Standardmäßig auf meiner Box aktiviert. Danke! – hek2mgl

0

Mit awk:

echo $line | awk '{ if ($2 == "VAN" || $2 == "DEN" || $2 =="DE" || $2=="DER" ) $2=""; if ($3 == "VAN" || $3== "DEN" || $3 =="DE" || $3=="DER" ) $3="" ; print }'