tipos que programacion ejemplos declarar comandos array shell unix

shell - que - Conciso y portátil "unirse" en la línea de comandos de Unix



shell unix comandos (9)

¿Cómo puedo unir varias líneas en una línea, con un separador donde estaban los caracteres de la nueva línea, y evitar un separador posterior y, opcionalmente, ignorar las líneas vacías?

Ejemplo. Considere un archivo de texto, foo.txt , con tres líneas:

foo bar baz

El resultado deseado es:

foo,bar,baz

El comando que estoy usando ahora:

tr ''/n'' '','' <foo.txt |sed ''s/,$//g''

Idealmente sería algo como esto:

cat foo.txt |join ,

Que es:

  1. la forma más portátil, concisa y legible.
  2. la forma más concisa usando herramientas Unix no estándar.

Por supuesto que podría escribir algo, o simplemente usar un alias. Pero estoy interesado en conocer las opciones.


¿Qué tal usar xargs?

para su caso

$ cat foo.txt | sed ''s/$/, /'' | xargs

Tenga cuidado con la longitud límite de entrada del comando xargs. (Esto significa que el archivo de entrada muy largo no puede ser manejado por esto).


Esta sed una línea debería funcionar -

sed -e :a -e ''N;s//n/,/;ba'' file

Prueba:

[jaypal:~/Temp] cat file foo bar baz [jaypal:~/Temp] sed -e :a -e ''N;s//n/,/;ba'' file foo,bar,baz

Para manejar las líneas vacías, puede eliminar las líneas vacías y canalizarlas al trazador de líneas anterior.

sed -e ''/^$/d'' file | sed -e :a -e ''N;s//n/,/;ba''


Forma simple de unir las líneas con espacio in situ utilizando ex (también ignorando las líneas en blanco), use:

ex +%j -cwq foo.txt

Si desea imprimir los resultados a la salida estándar, intente:

ex +%j +%p -scq! foo.txt

Para unir líneas sin espacios, use +%j! en lugar de +%j .

Para usar delimitador diferente, es un poco más complicado:

ex +"g/^$/d" +"%s//n/_/e" +%p -scq! foo.txt

donde g/^$/d (o v//S/d ) elimina las líneas en blanco y s//n/_/ es la sustitución que básicamente funciona igual que el uso de sed , pero para todas las líneas ( % ). Cuando finalice el análisis, imprima el búfer ( %p ). Y finalmente -cq! ejecutando vi q! comando, que básicamente se cierra sin guardar ( -s es silenciar la salida).

Tenga en cuenta que ex es equivalente a vi -e .

Este método es bastante portátil ya que la mayoría de los Linux / Unix vienen con ex / vi por defecto. Y es más compatible que con sed donde el parámetro en -i ( -i ) no es la extensión estándar y la utilidad en sí misma está más orientada a la transmisión, por lo tanto, no es tan portátil.


Mi respuesta es:

awk ''{printf "%s", ","$0}'' foo.txt

printf es suficiente. No necesitamos -F"/n" para cambiar el separador de campo.


Necesitaba lograr algo similar, imprimir una lista de campos separados por comas de un archivo, y estaba contento con conectar STDOUT a xargs y ruby , así:

cat data.txt | cut -f 16 -d '' '' | grep -o "/d/+" | xargs ruby -e "puts ARGV.join('', '')"


Perl:

cat data.txt | perl -pe ''if(!eof){chomp;$_.=","}''

o aún más corto y más rápido, sorprendentemente:

cat data.txt | perl -pe ''if(!eof){s//n/,/}''

o, si quieres:

cat data.txt | perl -pe ''s//n/,/ unless eof''


Solo por diversión, aquí hay una solución completamente integrada

IFS=$''/n'' read -r -d '''' -a data < foo.txt ; ( IFS=, ; echo "${data[*]}" ; )

Puede usar printf lugar de echo si la nueva línea final es un problema.

Esto funciona estableciendo IFS , los delimitadores que read se dividirán en solo línea nueva y no en otros espacios en blanco, luego le read a la read que deje de leer hasta que llegue a una nul , en lugar de la línea nueva que usualmente usa, y agregará cada elemento leído a la matriz ( -a ) de datos. Luego, en una subshell para no dañar el IFS del shell interactivo, establecemos IFS en y ampliamos el conjunto con * , que delimita cada elemento en el conjunto con el primer carácter en IFS


Tal vez un poco sorprendente, paste es una buena manera de hacer esto:

paste -s -d","

Esto no tratará con las líneas vacías que mencionaste. Para eso, canaliza tu texto a través de grep , primero:

grep -v ''^$'' | paste -s -d"," -


Tenía un archivo de registro donde algunos datos se dividieron en varias líneas. Cuando esto ocurrió, el último carácter de la primera línea fue el punto y coma (;). Me uní a estas líneas usando los siguientes comandos:

for LINE in ''cat $FILE | tr -s " " "|"'' do if [ $(echo $LINE | egrep ";$") ] then echo "$LINE/c" | tr -s "|" " " >> $MYFILE else echo "$LINE" | tr -s "|" " " >> $MYFILE fi done

El resultado es un archivo donde las líneas que se dividieron en el archivo de registro fueron una línea en mi nuevo archivo.