2012-01-10 15 views
9

Questo script batch DOS sta eliminando le righe vuote e non mostra le righe vuote nel file anche se sto usando il comando TYPE.exe per convertire il file per assicurarmi che il file sia ASCII in modo che il comando FIND sia compatibile con il file. Qualcuno può dirmi come rendere questo script includere le righe vuote?Il ciclo DOS per il ciclo con FIND.exe sta eliminando le righe vuote?

@ECHO off 
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE.exe "build.properties" ^| FIND.exe /V ""`) DO (
    ECHO --%%A-- 
) 
pause 

risposta

17

Questo è il comportamento progettato di FOR/F - non restituisce mai righe vuote. La soluzione è utilizzare FIND o FINDSTR per prefissare la linea con il numero di riga. Se è possibile garantire che nessuna riga inizi con il delimitatore del numero di riga, è sufficiente impostare il delimitatore appropriato e mantenere i token 1 *, ma utilizzare solo il secondo token.

::preserve blank lines using FIND, assume no line starts with ] 
::long lines are truncated 
for /f "tokens=1* delims=]" %%A in ('type "file.txt" ^| find /n /v ""') do echo %%B 

::preserve blank lines using FINDSTR, assume no line starts with : 
::long lines > 8191 bytes are lost 
for /f "tokens=1* delims=:" %%A in ('type "file.txt" ^| findstr /n "^"') do echo %%B 

::FINDSTR variant that preserves long lines 
type "file.txt" > "file.txt.tmp" 
for /f "tokens=1* delims=:" %%A in ('findstr /n "^" "file.txt.tmp"') do echo %%B 
del "file.txt.tmp" 

preferisco FINDSTR - è più affidabile. Ad esempio, TROVA può troncare le linee lunghe - FINDSTR non è lungo quanto legge direttamente da un file. FINDSTR fa cadere lunghe righe durante la lettura da stdin tramite pipe o reindirizzamento.

Se il file può contenere righe che iniziano con il delimitatore, è necessario conservare l'intera riga con il prefisso del numero di riga, quindi utilizzare Cerca e sostituisci per rimuovere il prefisso di riga. Probabilmente vuoi ritardare l'espansione quando trasferisci il %% A in una variabile d'ambiente, altrimenti qualsiasi! sarà corrotto. Ma più tardi all'interno del ciclo è necessaria un'espansione ritardata per effettuare la ricerca e la sostituzione.

::preserve blank lines using FIND, even if a line may start with ] 
::long lines are truncated 
for /f "delims=" %%A in ('type "file.txt" ^| find /n /v ""') do (
    set "ln=%%A" 
    setlocal enableDelayedExpansion 
    set "ln=!ln:*]=!" 
    echo(!ln! 
    endlocal 
) 

::preserve blank lines using FINDSTR, even if a line may start with : 
::long lines >8191 bytes are truncated 
for /f "delims=*" %%A in ('type "file.txt" ^| findstr /n "^"') do (
    set "ln=%%A" 
    setlocal enableDelayedExpansion 
    set "ln=!ln:*:=!" 
    echo(!ln! 
    endlocal 
) 

::FINDSTR variant that preserves long lines 
type "file.txt" >"file.txt.tmp" 
for /f "delims=*" %%A in ('findstr /n "^" "file.txt.tmp"') do (
    set "ln=%%A" 
    setlocal enableDelayedExpansion 
    set "ln=!ln:*:=!" 
    echo(!ln! 
    endlocal 
) 
del "file.txt.tmp" 

Se non è necessario preoccuparsi di convertire il file in ASCII, allora è più efficace di far cadere il tubo e lasciare che trovare o FINDSTR aprire il file specificato come argomento, o tramite reindirizzamento.

C'è un altro problema che ignora completamente FOR/F durante il processo di lettura. Sembra strano, ma è più efficiente. Non ci sono restrizioni nell'uso dell'espansione ritardata, ma sfortunatamente ha altre limitazioni.

1) linee devono essere risolti da < CR> < LF> (questo non sarà un problema se si fa la conversione di file TYPE)

2) linee devono essere < = 1021 byte lungo (trascurando la < CR> < LF>)

3) qualsiasi carattere di controllo finale viene rimosso da ogni riga.

4) deve leggere da un file - non è possibile utilizzare una pipe. Quindi nel tuo caso dovrai usare un file temporaneo per eseguire la tua conversione ASCII.

setlocal enableDelayedExpansion 
type "file.txt">"file.txt.tmp" 
for /f %%N in ('find /c /v "" ^<"file.txt.tmp"') do set cnt=%%N 
<"file.txt.tmp" (
    for /l %%N in (1 1 %cnt%) do(
    set "ln=" 
    set /p "ln=" 
    echo(!ln! 
) 
) 
del "file.txt.tmp" 
+1

Nessun problema, ma sono d'accordo che sembra male. È un'opzione più affidabile di "ECHO". Ci sono situazioni oscure in cui 'ECHO' può fallire, mentre' ECHO ('non fallisce mai.Il punto di entrambe le sintassi è di consentire l'output di una riga vuota – dbenham

+1

Puoi spiegare la riga" echo (! Ln! "? Isn ' C'è un problema con una parentesi di chiusura? Inoltre, la riga sopra manca la chiusura! char? – djangofan

+0

Finalmente ha funzionato. La tua conoscenza in questo settore è fantastica. Grazie. – djangofan

0

Grazie a dbenham, questo funziona, anche se è un po 'diverso dal suo suggerimento:

::preserve blank lines using FIND, no limitations 
for /f "USEBACKQ delims=" %%A in (`type "file.properties" ^| find /V /N ""`) do (
    set "ln=%%A" 
    setlocal enableDelayedExpansion 
    set "ln=!ln:*]=!" 
    echo(!ln! 
    endlocal 
) 
+1

Che cosa non funziona? Cosa stai vedendo? Vedo un problema 'ECHO! Ln!'stampa' ECHO è disattivato' se la riga è vuota! È per questo che ho usato 'ECHO (! Ln!' – dbenham

+0

Ok, l'ho aggiornato. Funziona ora. Grazie mille! Ora ho solo bisogno di integrarlo nel mio progetto. – djangofan

2

ho scritto un programma molto semplice che può servire come sostituto per FIND e FINDSTR comandi quando vengono utilizzati per questo scopo. Il mio programma è chiamato PIPE.COM e inserisce semplicemente uno spazio vuoto in linee vuote, in modo che tutte le linee possano essere elaborate direttamente dal comando FOR senza ulteriori regolazioni (a condizione che lo spazio inserito non importi).Eccolo:

@ECHO off 
if not exist pipe.com call :DefinePipe 
FOR /F "USEBACKQ delims=" %%A IN (`pipe ^< "build.properties"`) DO (
    ECHO(--%%A-- 
) 
pause 
goto :EOF 

:DefinePipe 
setlocal DisableDelayedExpansion 
set pipe=´)€ì!Í!ŠÐŠà€Ä!€ü.t2€ü+u!:æu8²A€ê!´#€ì!Í!².€ê!´#€ì!Í!²+€ê!´#€ì!Í!Šò€Æ!´,€ì!Í!"Àu°´LÍ!ëÒ 
setlocal EnableDelayedExpansion 
echo !pipe!>pipe.com 
exit /B 

EDIT: Addendum come risposta a un commento

Il codice a: DefinePipe subroutine creare un programma di 88 byte chiamato pipe.com, che in fondo fare un processo equivalente a questo codice pseudo-Batch:

set "space= " 
set line= 
:nextChar 
    rem Read just ONE character 
    set /PC char= 
    if %char% neq %NewLine% (
     rem Join new char to current line 
     set line=%line%%char% 
    ) else (
     rem End of line detected 
     if defined line (
     rem Show current line 
     echo %line% 
     set line= 
    ) else (
     rem Empty line: change it by one space 
     echo %space% 
    ) 
    ) 
goto nextChar 

questo modo, righe vuote nel file di input vengono cambiati da linee con uno spazio, in modo comando FOR/F non omettere più a lungo. Funziona "fino a quando lo spazio inserito non importa", come ho detto nella mia risposta.

Si noti che il programma pipe.com non funziona nelle versioni Windows a 64 bit.

Antonio linee

+0

Grazie per l'aiuto anche dai suggerimenti – djangofan

+0

Potresti confermare se il mio programma PIPE.COM ha risolto il tuo problema? – Aacini

+0

@Aacini - Potresti descrivere come funziona questa soluzione in modo più dettagliato? – user66001

1

uscita tra cui righe vuote

Ecco un metodo che ho sviluppato per mio uso.

Salvare il codice come un file batch dire, SHOWALL.BAT e passare il file di origine come parametro di riga di comando.

L'uscita può essere reindirizzata o convogliata.

@echo off 

for /f "tokens=1,* delims=]" %%a in ('find /n /v "" ^< "%~1"') do echo.%%ba 

exit /b 

ESEMPI:

ShowAllsource.txt

showallsource.txt>destination.txt

showallsource.txt| TROVA "stringa"

Una curiosità è l'inclusione della '^<' (reindirizzamento) al contrario di solo facendo quanto segue:

for /f "tokens=1,* delims=]" %%a in ('find /n /v "" "%~1"') do echo.%%ba 

Omettendo il reindirizzamento, una riga vuota leader è produzione.

+1

Bello, ma viene rimosso dai caratteri ']' dalle linee e 'echo' fallirà se esiste una riga come' \ .. \ .. \ Windows \ system32 \ calc.exe' – jeb

+1

@jeb, in realtà, in Almeno su Windows 7, non metterà a nudo tutti i caratteri ']'. Solo il primo, o fino a quando non incontra il '*'. –

0

Come accennato in this risposta alla domanda di cui sopra, non sembra che le linee vengono saltate per default utilizzando for /f in (almeno) Windows XP (Comunità - Si prega di aggiornare questa risposta testando i comandi batch di sotto della versione & Service Pack di Windows).


      EDIT: Per Jeb 's comment below, sembra che il comando ping, in almeno Windows XP, è
      causando for /f produrre <CR>' s invece di righe vuote (Se qualcuno sa esattamente perché, sarebbe
      apprezzare se potevano aggiornare questa risposta o comm ent).

      Come soluzione, sembra che la seconda predefinito delimitata gettone (<space>/%%b nell'esempio)
      restituisce come blank, che ha lavorato per la mia situazione di eliminare le righe vuote mediante un "genitore"
      if subordinata al secondo token all'inizio della for /f, in questo modo:

for /f "tokens=1,2*" %%a in ('ping -n 1 google.com') do (
     if not "x%%b"=="x" (
     {do things with non-blank lines} 
    ) 
    ) 



usando il codice seguente:

@echo off 
systeminfo | findstr /b /c:"OS Name" /c:"OS Version" 
echo.&echo. 
ping -n 1 google.com 
echo.&echo. 
for /f %%a in ('ping -n 1 google.com') do (echo "%%a") 
echo.&echo.&echo --------------&echo.&echo. 
find /? 
echo.&echo. 
for /f %%a in ('find /?') do (echo "%%a") 
echo.&echo. 
pause 

.... il seguente è quello che vedo su Windows XP, Windows 7 e Windows 2008, essendo gli unici tre versioni & service pack di Windows I avere accesso immediato a:

Windows XP Pro SP3

Windows 7 Enterprise SP1

Windows Server 2008 R2 Enterprise SP1

+0

Come ha detto dbenham: Per/f strisce sempre linee vuote. Nel tuo caso sembra che XP non rimuova le righe vuote, ma in realtà ottieni una riga con solo una virgola tra "Pinging" e "Reply". Ma questo non significa che FOR/F recuperi una linea vuota. La riga contiene un carattere '', quindi il cursore torna all'inizio della riga e la prima citazione viene sovrascritta dall'ultima citazione, tutto qui. Il comando ping sotto XP è semplicemente buggato – jeb

+0

Grazie a @jeb. Sono arrivato a questa pagina a causa del problema con (quello che pensavo al momento era) spazi extra, ma renditi conto ora (corretto da te) che sono solo i ritorni a capo in uscita su XP. Potete forse anche consigliare come si testerebbe il '' in una dichiarazione 'se non" x %% a "=" "'? – user66001

+0

Per rimuovere 'CR' puoi chiamare una funzione come': trimmer set "trim =% 1" 'questo funziona, poiché tutti i' CR' vengono rimossi dopo la fase di espansione percentuale. Ma per ulteriori domande, dovresti aprire una tua domanda – jeb

Problemi correlati