2016-09-08 3 views
4

ich derzeit Code haben, der wie folgt aussieht:Ästhetisch Pleasing String ersetzen Statement

$onestr = $twostr -replace "one","two" -replace "uno","dos" 

Ich mag würde es so zu formatieren:

$onestr = $twostr -replace "one","two" 
        -replace "uno","dos" 

, so dass die Aussagen oben auf jeder Stapel ersetzen andere.

Ich könnte Backtic als Zeilenfortsetzungszeichen verwenden, aber andere stackoverflow Fragen decken, warum das keine gute Idee ist.

Ich habe versucht, Code, der wie folgt aussieht:

$onestr = ($twostr -replace "one","two" 
        -replace "uno","dos" 
     ) 

Aber ich habe einen Fehler, dass die paren nicht abgestimmt ist.

Mein tatsächlicher Code hat mehrere ersetzen Anweisungen (nicht nur zwei).

+1

Hey Powershell-Team, kann ich ein '#requires -Semicolons'? –

+0

@BaconBits https://github.com/PowerShell/PowerShell/issues – Eris

+0

Wie beschrieben, ersetzen die Ersetzungsoperationen die Zeichenfolge in der Mitte der Wörter, z. "Hone the knife" wird "Htow the knife"! Ist das wünschenswert? Ein ganz anderer Ansatz könnte erforderlich sein, um eine Ganzwort-Semantik zu erhalten. –

Antwort

1

Wenn Sie nicht über eine Graviszeichen ` als Zeilenfortsetzungszeichen verwenden möchten, dann empfehle ich Ihnen nur diese unterschiedlichen Aussagen machen:

$onestr = $twostr -replace "one","two" 
$onestr = $onestr -replace "uno","dos" 
1

Ein sportlich, nicht ästhetisch, ansprechende Methode, deutlicher als

$onestr = $twostr -replace "one","two" <# 
       #> -replace "uno","dos" <# 
       #> -replace "foo","bar" 

mindestens es ist DRY er als Wiederholung der Zuweisungen

: a Graviszeichen könnte ein Kommentar sein!


Oder die schwere Artillerie: .NET Regex.Replace mit einem Skriptblock, so dass der Text nur einmal wiederholt wird:

function translate(
    [Parameter(Mandatory=$true, ValueFromPipeline=$true)] 
    [string]$text, 

    [Parameter(Mandatory=$true)] 
    [hashtable]$map, 

    [switch]$caseSensitive 
) { 
    $options = if ([bool]$caseSensitive) { '' } else { '(?i)' } 
    ([regex]($options + 
     ($map.Keys -replace '[$^*?.+|()\[\]{}\\]', '\$&' -join '|') 
    )).Replace($text, { param([string]$match) $map[$match] }) 
} 

'Abc' | translate -map @{ 
    'a'='1' 
    'b'='2' 
    'c'='3' 
} 

Es ist Groß- und Kleinschreibung standardmäßig.

+0

Interessanter Ansatz! – briantist

+0

Ich habe eine Single-Pass-Text-Ersatzmethode hinzugefügt. Habe es nicht bewertet, aber theoretisch könnte schneller sein als Multi-Pass-Ersatz. – wOxxOm

2

Wenn Sie viele Ersetzungen haben, was ist mit einem anderen Ansatz, der viel mehr Spielraum für die Ausrichtung der Ersatzpaare bietet, ohne den Block des Ersetzungscodes zu beeinflussen.

$onestr = 'one thing uno thing' 


$Pairs = @{ 
    'one' = 'two' 
    'uno' = 'dos' 
} 

$Pairs.GetEnumerator() | ForEach-Object { 
    $onestr = $onestr -replace $_.Name, $_.Value 
} 

$onestr 
2

Dies ist weniger verbreitet, vielleicht schrecklich, aber genau das Layout Sie fragen - mit .NET Framework String-Methode ersetzen anstelle des Powershell-Operator.

$onestr = 'one thing uno thing' 

$onestr. 
    Replace('one', 'two'). 
    Replace('uno', 'dos') 
+0

Ich denke, Sie könnten dies in Ihre aktuelle Antwort bearbeiten;) – briantist

+0

@briantist, aber ich möchte meine aktuelle Antwort als eine wortreiche, aber saubere Lösung upvoted, und ich erwarte, dass dies als unlesbar, überraschend und verwirrend abgelehnt und kritisiert wird. Sie sollten völlig unterschiedliche Antworten sein, vielleicht anonym gepostet als jemand anderes;) – TessellatingHeckler

+0

Nun, ich kann das nicht tun, also hier ist ein +1 trotzend! – briantist

1

Sie betrachten könnte eine metafunction mit einem [script] Parameter mit Ihrem Ausdruck in einer Zeile ohne Backticks auszupacken. Zum Beispiel könnte ein einfache Invoke-Unwrap metafunction ConvertTo-Spanish zu definieren, wie folgt verwendet werden: *

function Invoke-Unwrap([scriptblock]$sb) { 
    Invoke-Expression ($sb -replace '\r?\n\s*-', ' -') 
} 

Invoke-Unwrap { 
    function script:ConvertTo-Spanish([string]$str) { 
     $str 
      -replace "one","uno" 
      -replace "two","dos" 
      -replace "thing","lo" 
    } 
} 

ConvertTo-Spanish "thing one and thing two" 

Wie geschrieben Invoke-Unwrap sehr allgemein gehalten ist, ermöglicht es Zeilenumbruch vor jedem Betreiber oder Schalter beginnend mit einem „-“. Es könnte erweitert werden, um andere Operator-Zeichen am Anfang einer Zeile zuzulassen, was es erlaubt, arithmetische Ausdrücke in einer Wort-eingepackten Form zu schreiben. Ich denke ($sb -replace '\r?\n\s*([-+*/])', ' $1').

Oder, wenn Sie möchten, können Sie die Verarbeitung der an Invoke-Expression übergebenen Zeichenfolge verbessern, um Ihre eigene kleine domänenspezifische Sprache zu erstellen und vielleicht etwas SED-ähnliches zu implementieren.

  • Entschuldigt meine begrenzten Kenntnisse der spanischen Sprache ... :-)