2015-05-14 21 views
6

ich eine CSV in dem folgenden Dateiformat:Skript Powershell doppelte Anführungszeichen aus CSV zu entfernen, wenn Komma in doppelten Anführungszeichen besteht

In: "bob","1234 Main St, New York, NY","cool guy" 

ich doppelte Anführungszeichen zu entfernen suchen, die nicht innerhalb eines Komma haben :

Out: bob,"1234 Main St, New York, Ny",cool guy 

Gibt es eine Möglichkeit, dies in Powershell zu tun?

Ich habe überprüft:

  1. How to remove double quotes on specific column from CSV file using Powershell script
  2. http://blogs.technet.com/b/heyscriptingguy/archive/2011/11/02/remove-unwanted-quotation-marks-from-csv-files-by-using-powershell.aspx
  3. https://social.technet.microsoft.com/Forums/windowsserver/en-US/f6b610b6-bfb2-4140-9529-e61ad30b8927/how-to-export-csv-without-doublequote?forum=winserverpowershell

Antwort

3

Anpassung des Codes von "How to remove double quotes on specific column from CSV file using Powershell script":

$csv = 'C:\path\to\your.csv' 
(Get-Content $csv) -replace '(?m)"([^,]*?)"(?=,|$)', '$1' | 
    Set-Content $csv 

Die Regex (?m)"([^,]*?)"(?=,|$) ist passend zu jeder " + 0 or more non-commas + "vor ein Komma oder Zeilenende (erreicht mit einem positiven Vorgriffs und eine mehrzeilige Option (?m), die $ zu einer Newline, nicht nur das Ende der Zeichenfolge erzwingt).

Siehe regex demo

+0

Vielen Dank für Ihre Hilfe, Wiktor - Ich habe meine vorherigen Kommentare aufgeräumt. Schlussgedanke: Sie können das '(? M)' gut verwenden, wenn Sie 'Get-Content-Raw' (PSv3 +) verwenden, um die gesamte Datei in einer einzigen Zeichenfolge zu lesen, was ebenfalls die Geschwindigkeit erhöht. Um jedoch einen zusätzlichen abschließenden Zeilenumbruch zu vermeiden, muss die Ausgabe dann mit 'Set-Content -NoNewline' geschrieben werden - was PSv5 + ist:' (Get-Content-Raw $ csv) -replace '(? M) "([^ ,] *?) "(? =, | $) ',' $ 1 '| Set-Content -NoNewline $ csv' – mklement0

1

ich nicht genau weiß, was der Rest des Skriptes aussieht. Versuchen Sie etwas in dieser Richtung allerdings

(("bob","1234 Main St, New York, NY","cool guy") -split '"' | 
    ForEach-Object {IF ($_ -match ",") {'"' + $_ + '"' } ELSE {$_}}) -join "," 
0

Die bestehenden Antworten arbeiten gut mit dem Probeneingang:

  • Wiktor Stribiżew's helpful answer, welche Felder in doppelten Anführungszeichen identifiziert, die nicht , enthalten einen regulären Ausdruck verwenden, lädt die gesamte Eingabedatei in den Speicher Erstens, das ermöglicht, die Eingabedatei durch die Ergebnisse in einer einzigen Pipeline zu ersetzen.
    Während dies bequem ist - und schneller als zeilenweise Verarbeitung - der Vorbehalt ist, dass es möglicherweise keine Option für große Eingabedateien sein.
  • markg's helpful answer, die Zeilen in Felder durch " Chars. Unterteilt, ist eine Alternative für große Eingabedateien, da es die Pipeline verwendet, um die Eingabezeilen nacheinander zu verarbeiten.
    (Als Folge der Eingabedatei mit dem Ergebnis, werden nicht direkt aktualisiert.)

Wenn wir der Anforderung des OP verallgemeinern auch Felder mit eingebettet " Zeichen handhaben., müssen wir einen anderen Ansatz:

Folgende Felder müssen dann ihre doppelte Anführungszeichen umschließen behalten:

  • (notgedrungen) in doppelten Anführungszeichen Felder mit eingebetteten , Zeichen .; z.B..,
    "1234 Main St, New York, NY"
  • (notwendigerweise) in doppelten Anführungszeichen Felder mit eingebetteten " Zeichen, die pro RFC 4180 als "" entwertet werden müssen, d.h. verdoppelt; zB
    "Nat ""King"" Cole"

Hinweis:
- Wir sind nicht mit Feldern handelt, die Linie bricht eingebettet enthalten kann, als dass eine grundsätzlich andere Herangehensweise erfordern würde, weil sich geschlossene Linie-by Eine Zeilenbearbeitung ist dann nicht mehr möglich.
- Spitze des Hutes zu Wiktor Stribiżew, der mit dem regulären Ausdruck kam zu kräftig mit einer beliebigen Anzahl von eingebetteten doppelten Anführungszeichen, entkam als "" ein doppeltes Anführungszeichen Feld entspricht: "([^"]*(?:""[^"]*)*)"

# Create sample CSV file with double-quoted fields that contain 
# just ',', just embedded double quotes ('""'), and both. 
@' 
bob,"1234 Main St, New York, NY","cool guy" 
nat,"Nat ""King"" Cole Lane","cool singer" 
nat2,"Nat ""King"" Cole Lane, NY","cool singer" 
'@ | Set-Content ./test.csv 

Get-Content ./test.csv | ForEach-Object { 
    # Match all double-quoted fields on the line, and replace those that 
    # contain neither commas nor embedded double quotes with just their content, 
    # i.e., with enclosing double quotes removed. 
    ([regex] '"([^"]*(?:""[^"]*)*)"').Replace($_, { param($match) 
    $fieldContent = $match.Groups[1] 
    if ($fieldContent -match '[,"]') { $match } else { $fieldContent } 
    }) 
} 

Dies ergibt:

bob,"1234 Main St, New York, NY",cool guy 
nat,"Nat ""King"" Cole Lane",cool singer 
nat2,"Nat ""King"" Cole Lane, NY",cool singer 

Aktualisieren der Eingabedatei:

Wie in markg aNS Aufgrund der zeilenweisen Verarbeitung können Sie die Eingabedatei nicht direkt mit der Ausgabe in derselben Pipeline aktualisieren.
die iput Datei aktualisieren später eine temporäre Ausgabedatei und dann mit ihm die Eingabedatei ersetzen (... stellt die Get-Content Pipeline von oben, nur mit $csvFile statt ./test.csv):

$csvfile = 'c:\path\to\some.csv' 
$tmpFile = $env:TEMP\tmp.$PID.csv 
... | Set-Content $tmpFile 
if ($?) { Move-Item -Force $tmpFile $csvFile } 

Beachten Sie, dass Set-Content Verwendungen Die Standard-ASCII-Zeichencodierung Ihres Systems ist standardmäßig aktiviert (obwohl die help topicfalsely states ASCII).

Mit den -Encoding Parametern können Sie eine andere Codierung angeben, aber beachten Sie, dass UTF-16LE, die für die Standardeinstellung ist Out-File/> verursacht die CSV nicht ordnungsgemäß von Excel zum Beispiel erkannt Datei zu sein.

Verwandte Themen