Tengo un archivo .csv (en una Mac) que tiene un montón de líneas vacías, por ejemplo:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
Que quiero convertir a:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
Sé que debe haber un trazador de líneas, pero no sé awk o sed. Cualquier consejo muy apreciado!
shell
text-processing
sed
awk
pitosalas
fuente
fuente
Respuestas:
Puede usar el modo grep
-v
(inversión inversa) para hacer esto:Tenga en cuenta que estos deben ser archivos diferentes, debido a cómo funcionan los redireccionamientos de shell. El archivo de salida se abre (y se vacía) antes de leer el archivo de entrada. Si tiene más usos (no de forma predeterminada en Mac OS X), puede usar
sponge
para solucionar esto:Pero, por supuesto, es más difícil regresar si algo sale mal.
Si las "líneas en blanco" en realidad pueden contener espacios (parece que sí), puede usar esto en su lugar:
Eso ignorará las líneas en blanco, así como las líneas que contienen solo espacios en blanco. Por supuesto, puedes hacer la misma
sponge
transformación.fuente
egrep -v '^[[:space:]]*$'
... note grep -> egrep y el extraño nuevo patróniconv -f utf16le file.csv | head
oiconv -f utf16be file.csv | head
La opción más fácil es justa
grep .
. Aquí, el punto significa "unir cualquier cosa", por lo que si la línea está vacía, no coincide. De lo contrario, imprime toda la línea tal como está.fuente
Para eliminar líneas vacías, en su lugar , con ksh93:
El
<>;
operador de redirección es específico de ksh93 y es el mismo que el<>
operador estándar , excepto que ksh trunca el archivo después de que el comando ha finalizado.sed '/./!d'
es una forma complicada de escribirgrep .
, pero desafortunadamente GNU grep al menos se queja si su stdout apunta al mismo archivo que su stdin. Dirías que uno podría escribir:Pero desafortunadamente, hay un error en ksh93 (al menos mi versión (93u +)), ya que el archivo parece estar truncado a cero en ese caso.
Parece evitar ese error, pero ahora es mucho más complicado que el comando sed.
fuente
awk '/./' file 1<>; file
que funcionó. Para mí, eso es aún más claro quesed '/./!d'
Aquí hay una
Perl
frase para ello:EDITAR: Código mejorado basado en los comentarios de ruakh a continuación.
fuente
perl -ni -e '/./ and print' yourfile
$
es un ancla (es decir, ancho cero), por lo que excluye la nueva línea. En cuanto al espacio superfluo, es la razón por la que agregué/x
que no queríaPerl
intentar interpolar `$ \` en la expresión regular$
, dado que tienes el\n
. (Alternativamente, no necesita el\n
, dado que tiene el\s*
y el$
; pero creos/^\s*\n//
que aclara que se elimina la nueva línea). Tampoco necesita el/m
; No tiene ningún efecto sobre este comando. Y una vez que te deshagas del$
y del espacio, no necesitarás el/x
.\n
mismo se puede eliminar; lo que no puedes hacer es eliminar tanto el$
como el\n
. Entoncess/^\s*//
tendría el problema que usted describe, peros/^\s*$//
estaría bien, debido a la\s*
y la$
. (¿Ves lo que quiero decir?)$
puede coincidir antes de una nueva línea (siempre que sea el/m
indicador está activado, o el salto de línea es el último carácter de la cadena, o ambos), pero puede también coincidir con el final de la cadena. Por ejemplo,"abc" =~ m/^abc$/
es cierto. En el caso de\s*$
,\s*
es lo suficientemente codicioso como para consumir la nueva línea, y luego$
coincide con el final de la cadena. (Pero creo ques/^\s*\n//
es más claro, de todos modos, por lo que su respuesta está bien como está ahora.)Según la aclaración en los comentarios a su pregunta, algo como:
puede hacer lo que quieras
Un separador de registro vacío es un caso especial que indica
awk
que los registros deben ser párrafos (separados por secuencias de líneas vacías). Establecer el separador de registro de salida en la cadena vacía también significa que el contenido de esos párrafos (sin los separadores) debe concatenarse.1
es solo una verdadera condición para imprimir cada registro.Sin embargo, eso omitiría la nueva línea final, por lo que podría hacer:
fuente
Sé que esto habría sido más fácil si entregara el archivo, pero desafortunadamente contenía información confidencial que no podía compartir. Mientras tanto, me escribí un guión de rubí que parecía hacer el truco:
Gracias a todos por ayudar!
fuente
produce
fuente
Encontré una idea para una posible solución en stackoverflow .
sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv
Probablemente debería hacer una copia de seguridad de su archivo csv antes de probarlo, pero al menos para el ejemplo que proporcionó, funciona a la perfección.
En la respuesta se ofrece una buena explicación sobre el funcionamiento interno de esta expresión, solo la edité para buscar líneas que no terminen con un
"
([^"]\n
).fuente
Si, desde su propia respuesta, desea eliminar los caracteres de nueva línea contenidos dentro de las cadenas entre comillas, puede hacer lo siguiente:
También puede usar use perl's
-i
flag para editar los archivos en su lugar .O con GNU awk:
o:
(si estás compitiendo por el más corto)
Tenga en cuenta que aquellos suponen que no hay caracteres de comillas dobles escapadas en la entrada.
fuente
En efecto, parece que quiere más que eliminar líneas vacías, pero elimina cada secuencia de 2 o más caracteres de nueva línea.
Lo que podrías hacer con perl:
También puede usar use perl's
-i
flag para editar los archivos en su lugar .fuente
Hay una forma cada vez más corta de eliminar líneas vacías en
AWK
:awk 'NF' file
Pero para obtener la salida que desea, todo lo que necesita es un simple revestimiento:
awk 'NF {printf("%s ", $0); i++;} !(i % 2) {printf("\n");}' file
Explicación
En
AWK
, una línea vacía significa que la fila / registro no tiene campos, es decir, laNF
variable (Número de campos) es cero. El único trazo anterior solo se ejecutará cuandoNF > 0
, imprima todas las líneas, pero las vacías.El
i++
es el contador de líneas no vacías.El
!(i % 2)
se utiliza para imprimir dos líneas no vacías consecutivas en la forma de la salida deseada, es decir, cada vez que se encuentra un múltiplo de 2, lamodulo
instrucción!(i % 2)
produce 1, lo que termina la concatenación de dos líneas no vacías.fuente
Puede usar Vim en modo Ex:
v/./
encontrar líneas vacíasd
Eliminarx
guardar y cerrarfuente