2016-08-22 102 views
0

我嘗試更換一個CSV字符串的第n個元素,不知道他的價值。例如,以下是我的字符串:更換第n個元素爲CSV串

*;*;*;element_to_replace;*;* 

*帶有未定義的字符串,它可以是任何內容。

,所以我嘗試使用:

for /F "delims=" %%w in (file\workstation) do (
    set line=%%w 
    if !compt! NEQ 0 (
     set new_line=!line:*;*;*;*=*;*;*;new_value! 
     @echo !new_line! >> file\tmp_workstation 
    ) else (
     @echo !header_workstation! >> file\tmp_workstation 
    ) 
    set /A "compt+=1" 
) 

它不工作。難道我做錯了什麼 ?

+0

是:你不能在這裏使用通配符。 – Stephan

+0

不支持通配符?但是,本文檔(http://ss64.com/nt/syntax-replace.html)是給通配符的例子:SET _result =%_測試:* AB = XY% –

+0

這是一個通配符,而不是(複數)通配符。請注意,這是唯一的地方,它的工作原理。例如'set _result)%_ test:ab * = XY%does * not * work。 – Stephan

回答

2
@echo off 
setlocal enabledelayedexpansion 
REM you want to replace token 4: 
for /f "tokens=1-4,* delims=;" %%a in (t.csv) do (
    echo %%a;%%b;%%c;replaced;%%e 
) 

tokens=1-4,*就是說,將前四個令牌,第五令牌是「的路線的剩餘部分」。 %%a是第一個標記,%%b是你想寫token1;token2;token3,"replacement string for the fourth token(%%d)";"rest of the line" (fifth token)第二個等

+2

這是混淆太簡單了,它會失敗,像'Name ;; Phone; bla'這樣的空條目。你需要兩個FOR/F環 – jeb

+0

它的工作原理。謝謝 ! –

+0

文森特:爲@jeb指出:它的工作原理,只要你沒有(前四colums內)任何「空單元格」 – Stephan

1

假設的*字符不會將您的數據中出現字面上而且它也不含任何?馬克,你可以使用下面的代碼片段:

@echo off 
setlocal EnableExtensions DisableDelayedExpansion 

rem // Define constants here: 
set "INFILE=file\workstation" 
set "OUTFILE=file\tmp_workstation" 
set "SEPARATOR=;" 
set /A "COL_NUM=4" 
set "COL_NEWVAL=new_value" 

rem // A single redirection: 
> "%OUTFILE%" (
    set "HEADER=#" 
    rem // Read CSV file line by line: 
    for /F usebackq^ delims^=^ eol^= %%L in ("%INFILE%") do (
     set "LINE=%%L" 
     if defined HEADER (
      rem // Skip header from replacement: 
      set "NEW_LINE=%%L" 
      set "HEADER=" 
     ) else (
      set "NEW_LINE=" & set "SEP=" & set /A "IDX=0" 
      rem // Toggle delayed expansion to not lose any `!`: 
      setlocal EnableDelayedExpansion 
      set "LINE=!LINE:"=""!^" 
      rem // Use standard `for` loop to enumerate column values: 
      for %%I in ("!LINE:%SEPARATOR%=","!") do (
       endlocal 
       set /A "IDX+=1" 
       set "ITEM=%%~I" 
       setlocal EnableDelayedExpansion 
       rem // Replace column value if index matches: 
       if !IDX! EQU %COL_NUM% (
        endlocal 
        set "ITEM=%COL_NEWVAL%" 
        setlocal EnableDelayedExpansion 
       ) else (
        if defined ITEM set "ITEM=!ITEM:""="!^" 
       ) 
       rem /* Collect line string; 
       rem `for /F` loop to pass string beyond `endlocal` barrier: */ 
       for /F delims^=^ eol^= %%E in ("!NEW_LINE!!SEP!!ITEM!") do (
        endlocal 
        set "NEW_LINE=%%E" 
        setlocal EnableDelayedExpansion 
       ) 
       endlocal 
       set "SEP=%SEPARATOR%" 
       setlocal EnableDelayedExpansion 
      ) 
      endlocal 
     ) 
     rem // Output newly built line: 
     setlocal EnableDelayedExpansion 
     echo(!NEW_LINE! 
     endlocal 
    ) 
) 

endlocal 
exit /B 
+0

不錯,但矯枉過正。一個簡單的'set'line =「!line:; =」;「!」「」和'FOR/F「標記= 1-4 delims =;」 %% 1(「行!」)'應該夠安全分裂 – jeb

+0

@jeb,'爲/ F'不關心是否分隔符';'帶引號的領域內將出現在CSV數據在這種情況下,它不應該被視爲分隔符;由於OP沒有顯示數據的外觀如何,我選擇了安全的方式... – aschipfl

+0

引號不是用於檢測分隔符,而是爲了確保空字段的準確性。 'a ;; c; d'將轉換爲''a「;」「;」c「;」d「'因此您可以使用'FOR/F'標記= 1-4 delims =;」 (「!line!」)中的%% 1 DO回顯%%〜1 _ %%〜2 _ %%〜3 _ %%〜4',否則第二個(空)字段將被刪除,'%%〜2 '包含'c'而不是任何東西 – jeb