Saltar al contenido

Un comando para mostrar cada línea hacia adelante y luego hacia atrás

El tutorial o código que verás en este artículo es la solución más rápida y válida que encontramos a esta inquietud o problema.

Solución:

Una función de caparazón. Esto funcionará en cualquier shell que admita <<< here-strings, incluidos zsh y bash.

xyz()  
    while read line
    do 
        printf "%s " "$line"
        "[email protected]" <<<"$line"
    done


$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab

Habrá muchos problemas en la mayoría de los casos debido a la forma en que funciona el almacenamiento en búfer de stdio. Una solución para Linux podría ser usar el stdbuf programe y ejecute el comando con coproc, para que pueda controlar explícitamente el intercalado de la salida.

Lo siguiente asume que el comando generará una línea después de cada línea de entrada.

#!/bin/bash
coproc stdbuf -i0 -o0 "[email protected]"
IFS=
while read -r in ; do
    printf "%s " "$in"
    printf "%sn" "$in" >&$COPROC[1]
    read -r out <&$COPROC[0]
    printf "%sn" "$out"
done

Si se necesita una solución más general ya que el OP solo requiere cada línea de entrada al programa para finalmente generar una línea en lugar de inmediatamente, entonces se necesita un enfoque más complicado. Crear un bucle de eventos usando read -t 0 para intentar leer desde stdin y el co-proceso, si tiene el mismo "número de línea" para ambos, luego envíe, de lo contrario almacene la línea. Para evitar usar el 100% de la CPU si en alguna ronda del bucle de eventos ninguno estaba listo, introduzca un pequeño retraso antes de volver a ejecutar el bucle de eventos. Hay complicaciones adicionales si el proceso genera líneas parciales, estas deben almacenarse en búfer.

Si se necesita esta solución más general, escribiría esto usando expect ya que ya tiene un buen soporte para manejar la coincidencia de patrones en múltiples flujos de entrada. Sin embargo, esta no es una solución bash/zsh.

En este caso particular, usaría perl:

printf '%sn' foo bar | perl -Mopen=locale -lpe '$_ .= " " . reverse$_'
foo oof
bar rab

Que podría extender para trabajar también con grupos de grafemas:

$ printf '%sn' $'compliqueu301' |
    perl -Mopen=locale -lpe '$_ .= " " . join "", reverse/X/g'
compliqué éuqilpmoc

O zsh:

while IFS= read -r line; do
  print -r -- $line $(j::)$(s::Oa)line
done

Aunque evitaría usar while read bucles para procesar texto, incluso en zsh (incluso si en este caso particular, no es tan malo ya que solo se usan los comandos incorporados).

En el caso general, usar archivos temporales es probablemente el mejor enfoque. Con zshpuedes hacerlo con:

()paste -d ' ' $1 <(rev <$1) =(print -l foo bar)

(dónde =(...) se encarga de crear y limpiar el archivo temporal).

Reemplazándolo con tuberías y algún tipo de teeing es una receta para el punto muerto en el caso general. Consulte estas preguntas similares para conocer algunos enfoques y detalles sobre las situaciones de interbloqueo:

  • Divida una entrada para un comando diferente y combine el resultado
  • tee + cat: use una salida varias veces y luego concatene los resultados

Sección de Reseñas y Valoraciones

Si entiendes que te ha resultado de utilidad nuestro post, sería de mucha ayuda si lo compartes con el resto seniors y nos ayudes a extender nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *