Formato de salida de xargs

10

Me gustaría cambiar el formato de las pantallas de salida de xargs

cat k.txt 
1 
2 
3 

Y

cat k.txt | xargs 
1 2 3

Sin embargo, me gustaría tener 1, 2, 3o 1|2|3. ¿Alguna sugerencia?

Avinash
fuente
Ello podría lograrse con algo (no es exactamente esto) como xargs cat -n, pero es más fácil si usted acaba de recortar los caracteres de nueva línea, esto se puede lograr con echo $(cat), grepo awk(arrastre la forma de hacerlo). xargsno encaja bien para su propósito actual.
41754

Respuestas:

18

A continuación hay una docena de ejemplos de cómo puede tomar un archivo como este:

$ cat k.txt
1
2
3

y convertirlo a este formato:

1,2,3

Puede usar este comando para crear el archivo anterior si desea jugar:

$ cat <<EOF > k.txt
1
2
3
EOF

Los siguientes ejemplos se dividen en 2 grupos. Los que "trabajan" y los que "casi" trabajan. Los dejo porque muchas veces es tan valioso ver por qué algo no funciona, como ver por qué algo funciona.

La mayoría de los lenguajes de script con los que estoy familiarizado están representados. Algunos se representan varias veces, ya que, como sucede con el acrónimo famoso al que se hace referencia habitualmente en Perl, TIMTOWTDI .

NOTA: Puede cambiar la coma ( ,) en los ejemplos a continuación y reemplazarla con los caracteres que desee, es decir |.

Ejemplos que "funcionan"

Estos fragmentos de código producirán la salida deseada.

El pastecomando:

$ paste -s -d ',' k.txt 
1,2,3

El sedcomando:

$ sed ':a;N;$!ba;s/\n/,/g' k.txt
1,2,3

$ sed ':a;{N;s/\n/,/};ba' k.txt 
1,2,3

El perlcomando:

$ perl -00 -p -e 's/\n(?!$)/,/g' k.txt
1,2,3

$ perl -00 -p -e 'chomp;tr/\n/,/' k.txt
1,2,3

El awkcomando:

$ awk '{printf"%s%s",c,$0;c=","}' k.txt
1,2,3

$ awk '{printf "%s,",$0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk -vORS=, 1 k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk 'BEGIN {RS="dn"}{gsub("\n",",");print $0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

El pythoncomando:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,3

$ python -c "import sys; print sys.stdin.read().replace('\n', ',').rstrip(',')" <k.txt
1,2,3

Bash mapfileincorporado:

$ mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
1,2,3

El rubycomando:

$ ruby -00 -pe 'gsub /\n/,",";chop' < k.txt
1,2,3

$ ruby -00 -pe '$_.chomp!"\n";$_.tr!"\n",","' k.txt
1,2,3

El phpcomando:

$ php -r 'echo strtr(chop(file_get_contents($argv[1])),"\n",",");' k.txt
1,2,3

Advertencias

La mayoría de los ejemplos anteriores funcionarán bien. Algunos tienen problemas ocultos, como el ejemplo de PHP anterior. La función chop()es en realidad un alias rtrim(), por lo que los espacios finales de la última línea también se eliminarán.

También lo hace el primer ejemplo de Ruby y el primer ejemplo de Python. El problema es cómo todos están haciendo uso de un tipo de operación que esencialmente "corta", ciegamente, un personaje final. Esto está bien para el ejemplo que proporcionó el OP, pero se debe tener cuidado al usar este tipo de revestimientos para asegurarse de que se ajustan a los datos que procesan.

Ejemplo

Digamos nuestro archivo de muestra, se k.txtveía así en su lugar:

$ echo -en "1\n2\n3" > k.txt

Se ve similar pero tiene una ligera diferencia. No tiene una nueva línea final ( \n) como el archivo original. Ahora, cuando ejecutamos el primer ejemplo de Python, obtenemos esto:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,

Ejemplos que "casi" funcionan

Estos son los ejemplos de "siempre una dama de honor, nunca una novia" . La mayoría de ellos probablemente podrían adaptarse, pero cuando se trata de una posible solución a un problema, cuando se siente "forzado", ¡probablemente sea la herramienta incorrecta para el trabajo!

El perlcomando:

$ perl -p -e 's/\n/,/' k.txt
1,2,3,

El trcomando:

$ tr '\n' ','  < k.txt 
1,2,3,

Los comandos cat+ echo:

$ echo $(cat k.txt)
1 2 3

El rubycomando:

$ ruby -pe '$_["\n"]=","' k.txt
1,2,3,

Bash's while+ readincorporados:

$ while read line; do echo -n "$line,"; done < k.txt
1,2,3,
slm
fuente
1
En cuanto a awkprefiero una alternativa más corta:awk -vORS=, 1 k.txt
manatwork
No estoy seguro si CentOS tiene bash:mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
manatwork
No estoy seguro acerca de la nueva línea final. De acuerdo a mi prueba tu perly primero los tienes awktambién.
manatwork
Yo pondría pasteel de arriba. Eso es exactamente lo que paste -shay aquí. Es un comando estándar y sería el más eficiente. Todos los demás son excesivos y / o no son portátiles o tienen limitaciones.
Stéphane Chazelas
mapfilees relativamente nuevo, agregado en bash4.0.
manatwork
4

@slm ya dio una buena respuesta, pero como su pregunta "formato de salida de xargs"

xargs -I{} echo -n "{}|" < test.txt
  • -I es la opción "reemplazar cadenas".
  • {} es un marcador de posición para el texto de salida.
  • Esto es similar al uso de un par de llaves en "buscar".

Si quieres deshacerte del rastro |, puedes usar sedpara limpiar un poco:

$ xargs -I{} echo -n "{}|" < k.txt  | sed -e 's/|$//'
1|2|3
Rahul Patil
fuente
Eso agrega una tubería extra después de 3. "1 | 2 | 3 |". He tenido el mismo problema con un bucle while y una solución awk.
slm
Sí, si hay nueva línea .. tr, sedy otra también ..
Rahul Patil
2

Este es un hilo viejo, lo sé. El OP preguntó con un código simple como este. Para mantenerlo cerca del original, tengo una solución simple.

cat k.txt | xargs
1 2 3

usar sed

cat k.txt | xargs | sed 's/ /,/g'
1,2,3

o

cat k.txt | xargs | sed 's/ /|/g'
1|2|3

sed puede parecer un poco raro pero desglosado, tiene mucho sentido.

's es para sustituir. g 'es para global: sin esto, solo hará la primera sustitución en cada nueva línea. Como usa 'xargs', los muestra como una línea. Entonces obtendrás "1,2 3".

El delimitador se usa para la separación. Usé el / personaje. Un truco interesante: puede reemplazar el delimitador con la mayoría de cualquier otro carácter, siempre que mantengamos el mismo formato entre las comillas. Entonces esto también funcionaría ...

cat k.txt | xargs | sed 's# #,#g'

o

cat k.txt | xargs | sed 'sT T,Tg'

Obviamente, usar ciertos caracteres como delimitador puede ser confuso, así que sé inteligente.

Michael Bruce
fuente
0
xargs <k.txt | tr \  \|

No es necesario cat, simplemente pase la entrada del archivo y, si no se le da otro comando xargs, pasará su formato predeterminado, que es del tipo con /bin/echo's' (sin interpretaciones de barra invertida de escape c) .

xargseliminará los espacios en blanco de la cabeza / cola del archivo de entrada y comprimirá otras secuencias de espacios en blanco en un solo espacio. Esto significa que al pasar el archivo a partir trde xargscomo:

tr \\n \| <k.txt | xargs

...huellas dactilares...

1|2|3|

... yendo hacia el otro lado y operando solo en los argumentos que xargshace el delimitador de espacio ...

1|2|3\n

... porque xargsimprime la nueva línea final final (como se requiere para un archivo de texto) , pero no se trresponde de esa manera.

Sin embargo, tenga en cuenta que esta (o cualquier otra solución ofrecida aquí) no tiene en cuenta las xargscitas en la entrada. xargsrepartirá literalmente caracteres de espacio en blanco sin línea nueva / doble / con barra invertida en la entrada, que se pueden citar como:

xargs <<\IN
1    2'      3'\'      \'4
IN

1 2      3' '4
mikeserv
fuente