Eliminar el primer y el último carácter de cada línea de la línea de comando

8

Estoy tratando de eliminar el primer y el último carácter de cada línea en un archivo de texto y guardar la versión truncada resultante en un nuevo archivo. ¿Alguien tiene una idea sobre cómo hacerlo de manera eficiente usando awku otros programas / comandos de Linux específicamente para archivos grandes?

input.txt

(s,2,4,5,6)
"s,1,5,5,2"
{z,0,4,5,3}
[y,2,4,5,5]
(y,4,4,5,7)
(r,20,4,5,7)
(e,9,4,5,2)

Salida esperada.txt

s,2,4,5,6
s,1,5,5,2
z,0,4,5,3
y,2,4,5,5
y,4,4,5,79
r,20,4,5,7
e,9,4,5,2
pacodelumberg
fuente

Respuestas:

14

Otra forma solo por el gusto de hacerlo:

rev input | cut -c2- | rev | cut -c2-

(Nota: con GNU cut, solo funciona para caracteres hechos de un solo byte (como en su ejemplo)).

Drake Clarris
fuente
¡Agradable! Esto es significativamente más rápido que las soluciones sed y awk propuestas hasta ahora.
Gilles 'SO- deja de ser malvado'
Propuse esta respuesta para las personas que temen la sintaxis sed / awk / regex, pero no habrían imaginado que es más rápida, especialmente para archivos grandes, con tres tuberías y pasando todo el contenido a través de cada una. Habría pensado que sed o awk leer una línea a la vez sería más eficiente para archivos grandes.
Drake Clarris
3
¡Supongo que eso es lo que te llevará más de 40 años de optimización de muchas de estas utilidades * nix!
Drake Clarris
@Gilles, es más rápido que GNU se deposite en entornos locales utf8 para algunas formas de entrada, y depende de si está considerando la hora del reloj de pared o la hora de la CPU. ssedo el cofre de herramientas Heirloom sedpuede lograr un mejor rendimiento.
Stéphane Chazelas
@Gilles No hay entrada MAN para rev en Solaris 5.10. Terminé usandosed
ayrton_senna
10

Según su pregunta, elimine la última y la primera palabra del archivo de entrada de la siguiente manera:

sed 's/.$//; s/^.//' inputfile
Rahul Patil
fuente
Sería genial si pudiera referencia éstos contra la otra solución, s/.\(.*\).$/\1/. Podría ser más rápido debido a que no usa referencias posteriores, y la pregunta mencionó "archivos grandes".
2013
44
@ l0b0 probé con time yes | head -n 10000000 | COMMAND >/dev/null. Tengo rev input | cut -c2- | rev | cut -c2-→ 0.14s, sed 's,.\(.*\).$,\1,'→ 3.38s; awk '{print substr($0,2,length()-2);}'→ 3.50s; sed 's/.$//; s/^.//'→ 5.09s.
Gilles 'SO- deja de ser malvado'
@Gilles +1 Esa debería ser una respuesta.
l0b0
2
@Gilles, son líneas muy cortas. Creo que para líneas de 30 caracteres de ancho, la solución de @ RahulPatil es 3 veces más rápida con GNU sed que la de @ juampa. También. sed 's/.\(.*\)./\1/'parece ser más rápido que sed 's/^.\(.*\).$/\1/'(GNU sed nuevamente). Además, el rendimiento depende de la configuración regional (interpretación de lo que es un personaje) y la sedimplementación (en ese sentido, sed del cofre de herramientas de la herencia es considerablemente más rápido que GNU sed).
Stéphane Chazelas
5

Hay muchas posibilidades, como siempre

sed 's,.\(.*\).$,\1,g' your_file

Explicación

  • , - el delimitador de sed, también puede ser cualquier otro carácter, dado que se escapa donde sea necesario.
  • . Empareja un solo personaje
  • \(.*\) - Agrupe la parte restante, y esta se almacena para recuperar más.
  • . Empareja un solo personaje de nuevo
  • $ - Fin de la línea
  • \1 - generar el texto que coincide con el grupo de arriba
  • g reemplazar globalmente en la línea.
jpmuc
fuente
2
¿Por qué g? solo habrá una coincidencia por línea.
njsg
Tenga en cuenta que no eliminará nada de las líneas que tengan menos de 2 caracteres.
Stéphane Chazelas
3

También puedes hacerlo awksi lo prefieres

awk '{print substr($0,2,length()-2);}' input.txt > output.txt
Fuerte
fuente
2
tr -d '()[]{}"' < your_file

Esto debería funcionar también. Bien "traduce" cada uno de los caracteres a nada (eliminar).

La desventaja es que los eliminará si no son el primer / último personaje también. También echará de menos los caracteres finales que no incluyas en el ()[....

Mark Nichols
fuente