Tengo un archivo grande (9 GiB), codificado ASCII, delimitado por tuberías con terminaciones de línea de estilo UNIX; 0x0A.

Quiero muestrear los primeros 100 registros en un archivo para investigación. Lo siguiente producirá 100 registros (1 registro de encabezado y 99 registros de datos). Sin embargo, cambia las terminaciones de línea al estilo DOS / Winodws; CRLF, 0x0D0A.

Get-Content -Path .\wellmed_hce_elig_20191223.txt |
    Select-Object -first 100 |
    Out-File -FilePath .\elig.txt -Encoding ascii

Sé sobre iconv, recode y dos2unix. Esos programas no están en mi sistema y no pueden instalarse. He buscado y encontrado varios lugares sobre cómo llegar a CRLF. No he encontrado nada sobre cómo llegar o mantener LF.

¿Cómo puedo producir el archivo con terminaciones de línea LF en lugar de CRLF?

1
lit 10 feb. 2020 a las 23:16

2 respuestas

La mejor respuesta

Puede unir las líneas del cmdlet Get-Content con la línea nueva "` n "de Unix y guardarlo.

Algo así como

((Get-Content -Path .\wellmed_hce_elig_20191223.txt | 
        Select-Object -first 100) -join "`n") |
        Out-File -FilePath .\elig.txt -Encoding ascii -NoNewLine
1
Theo 10 feb. 2020 a las 20:30

Para complementar La útil respuesta de Theo con una optimización de rendimiento basada en el poco utilizado {{X0} } parámetro:

Set-Content -NoNewLine -Encoding ascii .\outfile.txt -Value (
  (Get-Content -First 100 -ReadCount 100 .\file.txt) -join "`n") + "`n"
)
  • -First 100 instruye a Get-Content para leer (como máximo) 100 líneas.

  • -ReadCount 100 hace que estas 100 líneas se lean y emitan a la vez , como una matriz , lo que acelera la lectura y el procesamiento posterior.

    • Nota: En PowerShell [Core] v7.0 + puede usar la abreviatura -ReadCount 0 en combinación con -First <n> para significar: lea las líneas <n> solicitadas como una sola matriz; debido a un error en versiones anteriores, incluido Windows PowerShell, -ReadCount 0 siempre lee el archivo completo , incluso en presencia de -First (también conocido como -TotalCount aka {{ X6}}).
      Además, incluso a partir de PowerShell [Core] 7.0.0-rc.2 (actual a partir de este escrito), combinando -ReadCount 0 con -Last <n> (también conocido como -Tail ) debe evitarse (por ahora): aunque la salida producida es correcta, detrás de escena es nuevamente todo el archivo que se lee; consulte este problema de GitHub.
  • Tenga en cuenta el + "`n", que garantiza que el archivo de salida también tendrá una nueva línea final (qué archivos de texto en el mundo Unix se espera que tengan).

Si bien lo anterior también funciona con -Last <n> (-Tail <n>) para extraer del final del archivo, la solución (más lenta) Select-Object de Theo ofrece más flexibilidad con respecto a extraer rangos arbitrarios de líneas, gracias a los parámetros disponibles -Skip, -SkipLast y -Index; sin embargo, ofrecer estos parámetros también directamente en Get-Content para un rendimiento superior se propone en esta solicitud de función de GitHub.

También tenga en cuenta que he usado Set-Content en lugar de Out-File.
Si sabe que está escribiendo texto , Set-Content es suficiente y generalmente faster (aunque en este caso esto no importará , dado que los datos a escribir se pasan como un valor único ).

Para obtener una descripción completa de las diferencias entre Set-Content y Out-File / > , consulte esta respuesta.


Set-Content vs. Out-File punto de referencia:

Nota: Este punto de referencia compara los dos cmdlets con respecto a escribir muchas cadenas de entrada recibidas a través de la canalización en un archivo.

# Sample array of 100,000 lines.
$arr = (, 'foooooooooooooooooooooo') * 1e5
# Time writing the array lines to a file, first with Set-Content, then
# with Out-File.
$file = [IO.Path]::GetTempFileName()
{ $arr | Set-Content -Encoding Ascii $file }, 
{ $arr | Out-File -Encoding Ascii $file } | % { (Measure-Command $_).TotalSeconds }
Remove-Item $file

Ejemplo de sincronización en segundos desde mi VM Windows 10 con Windows PowerShell v5.1:

2.6637108 # Set-Content
5.1850954 # Out-File; took almost twice as long.
1
mklement0 11 feb. 2020 a las 21:43