Cómo truncar la segunda columna a la longitud dada

9

Entrada dada del formulario

XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar foolkasjfdrte

¿Cómo puedo truncar solo la segunda columna? El delimitador es TAB y la segunda columna debe tener como máximo 75 caracteres.

LoukiosValentine79
fuente
Un poco más genérico:awk 'BEGIN{OFS=FS="\t"} {$2=substr($2,1,75)}1' file
fedorqui
¿Desea truncar (eliminar caracteres después del 75) o doblar (imprimirlos en otra línea)? Además, ¿deben contarse los espacios hacia los 75 caracteres o no?
terdon

Respuestas:

7

Si desea imprimir solo los primeros 75 caracteres de la segunda columna (incluidos los espacios y suponiendo que solo haya dos columnas en el archivo), puede hacer lo siguiente:

$ perl -pe 's/(\t.{75}).*/$1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

O con GNU sed:

$ sed 's/\(.*\t.\{75\}\).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

O:

$ sed -r 's/(.*\t.{75}).*/\1/' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Alternativamente, puede usarlo fold, diciéndole que corte los primeros 91 caracteres (eso es 8 para el identificador y otros 8 para la pestaña), e imprimiendo solo la primera línea:

$ fold -w 91 file | head -n1
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

Si su archivo puede tener más de 2 columnas y solo desea truncar la segunda, puede hacerlo (que, como acabo de notar, es solo una nueva redacción de la respuesta de Stephen ):

$ awk -F"\t" -vOFS="\t" '{$2=substr($2,1,75)}1;' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool

O (tenga en cuenta que esto se romperá si los primeros 75 caracteres de la segunda columna se pueden interpretar como una expresión regular):

$ perl -F"\t" -pale 's/$F[1]/substr($F[1],0,75)/e' file
XY981743    foobarlkasdf saflkas asfZR!sgfad asdSAD asdsadf SAdfasdf46lk lksad bar fool
terdon
fuente
Esos pueden truncar otras columnas que la segunda. Su primer sedcomando también está usando un GNUism ( \t).
Stéphane Chazelas
@ StéphaneChazelas qué ? \tQué es un GNUismo? ¿Seriamente? ¿Cuál es la forma portátil de describir una pestaña entonces?
terdon
1
Insértela textualmente para ver mi respuesta. La única secuencia de escape reconocida de forma portátil en el LHS es \n(y de nuevo no dentro [...]con muchas implementaciones), ninguna en el RHS.
Stéphane Chazelas
@ StéphaneChazelas maldita sea, gracias. También agregué una solución que puede manejar múltiples columnas.
terdon
Tu último perltiene poco sentido. Piense, por ejemplo, en una entrada comoaba\t.*
Stéphane Chazelas
10

Usando awk, divide el archivo usando pestañas y genera el primer campo completo y los primeros 75 caracteres (como máximo) del segundo:

awk -F "\t" 'BEGIN { OFS=FS }; { print $1, substr($2, 1, 75); }'

Como señaló fedorqui , puede manejar archivos con más de dos campos reemplazando los campos que necesita truncar:

awk -F "\t" 'BEGIN { OFS=FS }; { $2=substr($2, 1, 75); print }'

Puede aplicar el substra múltiples campos haciendo un bucle sobre ellos si es necesario.

Stephen Kitt
fuente
@ Stéphane, ¿en qué casos son los más ;necesarios?
Stephen Kitt
Son requeridos por POSIX. Ahora no conozco ninguna implementación donde se requieran, pero cuando solicité que ese requisito de POSIX se relaje, fue rechazado por el responsable de gawk (donde todos los ejemplos en el documento tienen el;).
Stéphane Chazelas
Ah, es bueno saberlo, gracias! Entonces, la especificación y la documentación son más estrictas que todas las implementaciones ...
Stephen Kitt
todas las implementaciones que conozco al menos (no tantas). El punto es omitir que el delimitador crea una sintaxis no estándar. Por lo tanto, las implementaciones actuales y futuras pueden y tienen derecho a ahogarse o introducir extensiones que lo utilizan (como una excepción que maneja una, /pattern/ {action} {exception-handling}por ejemplo). Ahora, eso sería extremadamente improbable dado que omitirlos ;es bastante común.
Stéphane Chazelas
4

Portable / POSIXly con sed:

tab=$(printf '\t')
sed "s/\($tab[^$tab]\{0,75\}\)[^$tab]*/\1/"

O para truncar cada columna:

sed "s/\([^$tab]\{75\}\)[^$tab]*/\1/g"
Stéphane Chazelas
fuente
2

Si solo hay 2 columnas:

sed -r 's/^([^\t]*\t)(.{0,75}).*/\1\2/'

{0,75}significa seleccionar de 0 a 75 caracteres.
.* es la sección eliminada más allá de char 75.


Si hay 2 o más columnas:

sed -r 's/^([^\t]*\t)([^\t]{0,75})[^\t]*(.*)/\1\2\3/' file

[^\t]* es la sección eliminada más allá de char 75.

Peter.O
fuente
Tenga en cuenta que eso supone GNU sedy que POSIXLY_CORRECTno está en el medio ambiente ..
Stéphane Chazelas