Búsqueda entre líneas

Este otro caso, tambien esta tomado de [6] y [7]. Se trata de extender la capacidad de búsqueda de grep, de modo que el patrón pueda ser encontrado incluso si se encuentra diseminado entre a lo mas dos líneas. El script presentado es una ligera variante del que aparece en [6] y escribe la(s) líneas que casan precedidas del número de la segunda línea.
$ cat phrase
#! /bin/sh
# phrase -- search for words across two lines.
# Prints the line number
# $1 = search string; remaining args = filenames
search=$1
shift
for file
do
sed -n '
  /'"$search"'/b final
  N
  h
  s/.*\n//
  /'"$search"'/b final
  g
  s/ *\n//
  /'"$search"'/{
    g
    b final
  }
  g
  D
:final
  =
  p
' $file
done
Así, con el ejemplo ``multiline.test'' usado anteriormente obtenemos la siguiente salida:
$ phrase "Owner and Operator Guide" multiline.test
3
Section 3.1 in the Owner and
Operator Guide for a description of the tape drives available for the Owner
7
Consult Section 3.1 in the Owner and Operator
Guide for a description of the tape drives
10
Look in the Owner and Operator Guide, we mean the Owner
14
Two manuals are provided including the Owner and
Operator Guide and the User Guide.
16
The Owner and Operator Guide is shipped with your system.
19
Look in the Owner
and Operator Guide shipped with your system.
Primero se busca el patrón /'"$search"'/ en la línea actual. Observe el habilidoso uso de las comillas simples y dobles para permitir la sustitución de la variable. La primera comilla simple cierra la comilla simple al final de la línea 10. Las comillas dobles hacen que la shell sustituya permite continuar el texto sin sustituciones.

Si se encuentra el patrón de búsqueda, imprimimos el número de línea (comando =) y la línea. Si no, leemos la siguiente línea, formando un patrón multilínea. Salvamos las dos líneas en el hold space. Entonces intentamos buscar el patrón /'"$search"'/ en la línea que acaba de incorporarse. Es por eso que eliminamos del espacio de patrones la primera línea con la orden s/ *\n//. Si se encuentra, imprimimos y se repite el ciclo. Si no, recuperamos las dos líneas del hold space sustituimos el retorno de carro por un blanco y realizamos una nueva busqueda. Si tiene éxito, se obtienen las dos líneas y se imprimen. En caso contrario, esto es, si el patrón no se ha encontrado en ninguna de las dos líneas, es necesario preservar la última para el siguiente ciclo. Por eso, se obtienen una vez mas las líneas del hold space y se suprime con D la primera de ellas. Dado que D devuelve el control al comienzo del script, la segunda línea no es eliminada. De todos modos, el script no es capaz de captar cuando un prefijo del patrón aparece al final de esta segunda línea, como muestra el ejemplo de prueba. En el primer párrafo el patrón se encuentra dos veces y sólo es encontrado una.

Casiano Rodríguez León
2013-04-23