Saltar la navegación

Comando b (branch)

Con el comando b (branch) provocamos un salto incondicional a una etiqueta del script sin reiniciar el ciclo de sed. Su sintaxis es la siguiente:

b [etiqueta]

En el caso de que no se especifique una etiqueta estaríamos forzando el inicio de un nuevo ciclo previo envío de la zona de trabajo a la salida estándar.

Como el comando b cuando lleva etiqueta no reinicia el ciclo, se suele utilizar dentro del bucle los comandos n y/o N para poder avanzar con el flujo de entrada.

Si este comando va acompañado de un ámbito, el salto se convertiría en condicional. Podemos usar esto para crear bucles:

:salto
comando1
comando2
...
comandoN
ámbito b salto
:salto1
ámbito b salto2
comando1
comando2
...
comandoN
b salto1
:salto2

El siguiente script de bash usa la orden sed para mostrar la información del flujo de entrada con la anchura deseada.

#!/bin/bash

declare longitud fichero script

if [ -z "$1" ]; then
  echo "Uso: muestra longitudDeLinea fichero" 1>&2
  exit 1
else
  suma=$(($1 + 1))
  if [ $suma -lt 2 ]; then
    echo "Error: La longitud de la línea debe ser >= 1" 1>&2
    echo "Uso: muestra longitudDeLinea fichero" 1>&2
    exit 2
  else
    longitud=$1
  fi
fi

if [ -z "$2" ]; then
    echo "Uso: muestra longitudDeLinea fichero" 1>&2
    exit 3
else
  if [ "$2" != "-" -a ! -f "$2" ]; then
    echo "El fichero '$2' no existe" 1>&2
    exit 4
  else
    fichero=$2
  fi
fi

# Nombre del script de sed
script="script-$RANDOM$RANDOM.sed"

# Creamos el script de sed
echo ":nuevaLinea" >> $script # Etiqueta del bucle externo. Al inicio, empieza el ciclo cargando una línea
echo "N" >> $script           # Cargamos una nueva línea en la zona de trabajo
echo "s/\n/ /g" >> $script    # Sustituimos cada \n por un espacio
echo ":trocear" >> $script    # Etiqueta del bucle interno que va haciendo los trozos
echo "s/(.{$longitud})/\1\n/" >> $script  # Hacemos el trozo y lo convertimos en línea
echo "/\n/ { P ; s/.*\n// ; b trocear }" >> $script  # Todo esto si el trozo se ha hecho
                                                     # Visualizamos la primera línea (P)
                                                     # La borramos (s/.*\n//)
                                                     # Volvemos a trocear si ha texto suficiente (b trocear)
echo "b nuevaLinea" >> $script  # Si no se pudieron hacer más trozos saltamos al inicio para cargar otra línea con N

# Ejecutamos sed
sed -E -f $script $fichero
# Borramos el script de sed
rm -f $script

Veamos el script en funcionamiento:

$ ls -l f g
-rw-r--r-- 1 fran fran 13 abr 11 20:38 f
-rw-r--r-- 1 fran fran  7 abr 11 20:38 g
$ ls -l f g | ./muestra.sh 10 -
-rw-r--r--
 1 fran fr
an 11 abr 
11 10:38 f
 -rw-r--r-
- 1 fran f
ran  7 abr
 11 12:21 
g
$ ls -l f g | ./muestra.sh 15 -
-rw-r--r-- 1 fr
an fran 11 abr 
11 10:38 f -rw-
r--r-- 1 fran f
ran  7 abr 11 1
2:21 g

El script de sed concreto para una anchura de 10 caracteres sería así:

:nuevaLinea
N
s/\n/ /g
:trocear
s/(.{10})/\1\n/
/\n/ { P ; s/.*\n// ; b trocear }
b nuevaLinea