¿Hay alguna forma de saber sed a la salida sólo capturado grupos? Por ejemplo, dada la entrada:

This is a sample 123 text and some 987 numbers

y el patrón:

/([\d]+)/

Podría obtener sólo 123 y 987 de salida en el modo de formato de vuelta referencias?

InformationsquelleAutor Pablo | 2010-05-06

8 Comentarios

  1. 293

    La clave para conseguir que el trabajo es contar sed para excluir lo que no quieres ser la salida, así como la especificación de lo que usted desea.

    string='This is a sample 123 text and some 987 numbers'
    echo "$string" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/ /p'

    Este dice:

    • no predeterminada para la impresión de cada línea (-n)
    • excluir cero o más dígitos
    • incluir uno o más dígitos
    • excluir a uno o más dígitos
    • incluir uno o más dígitos
    • excluir cero o más dígitos
    • de impresión de la sustitución (p)

    En general, en sed captura de los grupos de uso de los paréntesis y de salida de lo que usted capture el uso de un nuevo referencia:

    echo "foobarbaz" | sed 's/^foo\(.*\)baz$//'

    de salida será de «bar». Si utiliza -r (-E para OS X) para extended regex, usted no necesita para escapar de los paréntesis:

    echo "foobarbaz" | sed -r 's/^foo(.*)baz$//'

    No puede ser de hasta 9 captura de los grupos y sus referencias. La parte de atrás de referencias se numeran en el orden de los grupos que aparecen, pero puede ser utilizado en cualquier orden y puede ser repetido:

    echo "foobarbaz" | sed -r 's/^foo(.*)b(.)z$/  /'

    salidas «un bar».

    Si usted tiene GNU grep (también puede funcionar en BSD, incluyendo OS X):

    echo "$string" | grep -Po '\d+'

    o variaciones tales como:

    echo "$string" | grep -Po '(?<=\D )(\d+)'

    La -P opción permite Expresiones Regulares Compatibles con Perl. Ver man 3 pcrepattern o hombre
    3 pcresyntax
    .

    • Como una nota, OSX Mountain Lion ya no admite PCRE en grep.
    • Como nota al margen, grep -o no se admite la opción en Solaris 9. También, Solaris 9 no soporta la sed opción-r. 🙁
    • Pregunte a su administrador de sistema para instalar gsed. Usted se sorprenderá de lo que un par de donuts va a llegar…
    • En OSX (incluyendo Mountain Lion) puede utilizar brew para instalar grep de homebrew-dupes y, a continuación, utilizar la (muy útil) -P opción (:
    • Tenga en cuenta que usted puede ser que necesite para el prefijo ‘(‘ y ‘)’ con ‘\’, no sé por qué.
    • Si te refieres a la sed ejemplo, si utiliza el -r opción (o -E para OS X, si mal no recuerdo) que no necesita para escapar de los paréntesis. La diferencia es que entre las expresiones regulares y expresiones regulares extendidas (-r).
    • He encontrado el aceptado respuesta confusa b/c que incorpora una gran regexp con el ejemplo, lo que es difícil extraer la información necesaria: En el sed debe escapar paréntesis \(.*\), el acceso de captura de los grupos con \1, \2, ect..
    • Usted no necesita para escapar de los paréntesis si el uso extendido de regex, como tengo en mi ejemplo, mediante la inclusión de la -r opción. Estoy de acuerdo en que me puede destacar la captura en mi respuesta. Voy a editar en consecuencia. La razón por la regex es grande es porque implementa la funcionalidad que el OP estaba buscando en el Perl de estilo expresión \d y la cadena de entrada.

  2. 52

    Sed tiene hasta nueve recordado patrones pero necesitas utilizar escapó paréntesis para recordar partes de la expresión regular.

    Ver aquí para los ejemplos y las más detalle

    • sed -e 's/version=\(.+\)/\1/' input.txt esto todavía la salida de la totalidad input.txt
    • comentario debe ser aceptada respuesta
    • En su patrón tiene que escribir \+ en lugar de +. Y yo no entiendo por qué la gente usa -e para un solo comando sed.
    • uso sed -e -n 's/version=\(.+\)/\1/p' input.txt ver: mikeplate.com/2012/05/09/…
    • Me gustaría sugerir el uso de sed -E el uso de los llamados «modernos» o «extendido» expresiones regulares que se ven mucho más cerca de Perl/Java/JavaScript/Go/lo que sea sabores. (Compare con grep -E o egrep.) La sintaxis por defecto tiene esas extrañas escapar de las reglas y es considerado como «obsoleto». Para obtener más información sobre las diferencias entre los dos, ejecute man 7 re_format.
  3. 30

    puede utilizar grep

    grep -Eow "[0-9]+" file
    • Absolutamente de acuerdo con usted. ¿Cómo puedo obtener greo a la salida sólo capturado grupos?
    • es por eso que el o opción es no – unixhelp.ed.ac.reino unido/CGI/hombre-cgi?grep : -o, –sólo coincidencia de Mostrar sólo la parte de una coincidencia de la línea que coincide con el PATRÓN
    • F: yo entiendo la parte coincidente, pero no es del grupo de captura. Lo que yo quiero es tener como esto ([0-9]+).+([abc]{2,3}) así que hay 2 grupos de captura. Quiero SÓLO de salida de los grupos de captura por retro-referencias o de alguna otra cosa.
    • Hola Michael. Se las arregló para extraer el enésimo grupo capturado por grep ?
    • grep es sólo transmitir lo que coincide con. Para darle varios grupos, el uso de múltiples expresiones: grep -Eow -e "[0-9]+" -e "[abc]{2,3}" no sé cómo se podría exigir a estas dos expresiones en una línea aparte de tuberías del anterior grep (que aún así podría no funcionar si el patrón coincide con más de una vez en una línea).
    • También, usted no puede hacer echo "a 10 b 12" | grep -Eo "a ([0-9]+)" y obtener el «10». Pero esto funciona: echo "a 10 b 12" | grep -Eo "a ([0-9]+)" | sed 's/a //'

  4. 9

    Dar y utilizar Perl

    Desde sed no cortar, vamos a tirar la toalla y el uso de Perl, por lo menos es LSB mientras grep GNU extensiones no 🙂

    • Imprimir toda la parte coincidente, no coincidentes grupos o lookbehind necesarios:

      cat <<EOS | perl -lane 'print m/\d+/g'
      a1 b2
      a34 b56
      EOS

      De salida:

      12
      3456
    • Solo partido por línea, a menudo, estructurada en campos de datos:

      cat <<EOS | perl -lape 's/.*?a(\d+).*/$1/g'
      a1 b2
      a34 b56
      EOS

      De salida:

      1
      34

      Con lookbehind:

      cat <<EOS | perl -lane 'print m/(?<=a)(\d+)/'
      a1 b2
      a34 b56
      EOS
    • Varios campos:

      cat <<EOS | perl -lape 's/.*?a(\d+).*?b(\d+).*/$1 $2/g'
      a1 c0 b2 c0
      a34 c0 b56 c0
      EOS

      De salida:

      1 2
      34 56
    • Varios partidos por línea, a menudo los datos no estructurados:

      cat <<EOS | perl -lape 's/.*?a(\d+)|.*/$1 /g'
      a1 b2
      a34 b56 a78 b90
      EOS

      De salida:

      1 
      34 78

      Con lookbehind:

      cat EOS<< | perl -lane 'print m/(?<=a)(\d+)/g'
      a1 b2
      a34 b56 a78 b90
      EOS

      De salida:

      1
      3478
    • Lo que no se obtiene con el final de la pregunta : «con sed» ?
    • Los empleados no les importa.
    • he encontrado esta útil. no toda la línea de comandos regex los problemas deben ser resueltos con sed.
  5. 8

    Creo que el modelo dado en la pregunta era a modo de ejemplo solamente, y el objetivo era igualar cualquier patrón.

    Si usted tiene un sed con la extensión de GNU que permite la inserción de una nueva línea en el espacio en el patrón, una sugerencia es:

    > set string = "This is a sample 123 text and some 987 numbers"
    >
    > set pattern = "[0-9][0-9]*"
    > echo $string | sed "s/$pattern/\n&\n/g" | sed -n "/$pattern/p"
    123
    987
    > set pattern = "[a-z][a-z]*"
    > echo $string | sed "s/$pattern/\n&\n/g" | sed -n "/$pattern/p"
    his
    is
    a
    sample
    text
    and
    some
    numbers

    Estos ejemplos son con tcsh (sí, yo saber su mal shell) con CYGWIN. (Edit: Para bash, quitar conjunto, y los espacios alrededor de =.)

    • gracias, sin embargo, basado en mi tarea me siento como grep es más natural, como ghostdog74 sugerido. Solo falta averiguar cómo hacer grep salida de la captura de grupos, no en todo el partido.
    • Sólo una nota, pero el signo ‘+’ significa ‘uno o más’, que elimina la necesidad de repetir lo mismo en los patrones. Así, «[0-9][0-9]*» sería «[0-9]+»
    • Con el fin de utilizar el +, usted necesita para escapar de ella o el uso de la -r opción (-E para OS X). También puede utilizar \{1,\} (o -r o -E sin el escape).
  6. 7

    ejecutar(s) de dígitos

    Esta respuesta funciona con cualquier recuento de grupos de dígitos. Ejemplo:

    $ echo 'Num123that456are7899900contained0018166intext' |
    > sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/ /gp'
    123 456 7899900 0018166

    Respuesta ampliada.

    ¿Hay alguna forma de saber sed de salida sólo capturado grupos?

    Sí. sustituir todo el texto por la captura de grupo:

    $ echo 'Number 123 inside text' | sed 's/[^0-9]*\([0-9]\{1,\}\)[^0-9]*//'
    123
    
    s/[^0-9]*                           # several non-digits
             \([0-9]\{1,\}\)            # followed by one or more digits
                            [^0-9]*     # and followed by more non-digits.
                                   // # gets replaced only by the digits.

    O con sintaxis extendida (menos de acentos graves y permitir el uso de +):

    $ echo 'Number 123 in text' | sed -E 's/[^0-9]*([0-9]+)[^0-9]*//'
    123

    Para evitar la impresión de que el texto original cuando no hay ningún número, uso:

    $ echo 'Number xxx in text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*//p'
    • (-n) no imprimir la entrada por defecto.
    • (/p) imprimir sólo si el reemplazo se hizo.

    Y a la coincidencia de varios números (y también imprimir):

    $ echo 'N 123 in 456 text' | sed -En 's/[^0-9]*([0-9]+)[^0-9]*/ /gp'
    123 456

    Que funciona para cualquier recuento de dígitos que se ejecuta:

    $ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
    $ echo "$str" | sed -En 's/[^0-9]*([0-9]{1,})[^0-9]*/ /gp'
    123 456 7899900 0018166

    Que es muy similar al comando grep:

    $ str='Test Num(s) 123 456 7899900 contained as0018166df in text'
    $ echo "$str" | grep -Po '\d+'
    123
    456
    7899900
    0018166

    Sobre \d

    y el patrón: /([\d]+)/

    Sed no reconoce el ‘\d’ (acceso directo) sintaxis. El equivalente en ascii utilizado anteriormente [0-9] no es exactamente equivalente. La única solución alternativa es utilizar una clase de caracteres: ‘[[:digit:]]`.

    La respuesta seleccionada el «clases de caracteres» para construir una solución:

    $ str='This is a sample 123 text and some 987 numbers'
    $ echo "$str" | sed -rn 's/[^[:digit:]]*([[:digit:]]+)[^[:digit:]]+([[:digit:]]+)[^[:digit:]]*/ /p'

    Que la solución sólo funciona para (exactamente) dos carreras de dígitos.

    De curso, ya que la respuesta está siendo ejecutado en el interior de la concha, podemos definir un par de variables para realizar dicha respuesta corta:

    $ str='This is a sample 123 text and some 987 numbers'
    $ d=[[:digit:]]     D=[^[:digit:]]
    $ echo "$str" | sed -rn "s/$D*($d+)$D+($d+)$D*/ /p"

    Pero, como ya se ha explicado, el uso de un s/…/…/gp comando es mejor:

    $ str='This is 75577 a sam33ple 123 text and some 987 numbers'
    $ d=[[:digit:]]     D=[^[:digit:]]
    $ echo "$str" | sed -rn "s/$D*($d+)$D*/ /gp"
    75577 33 123 987

    Que abarcará tanto repetirse se ejecuta de dígitos y escribir un breve(er) comando.

    • Sorprendido después de leer el alto votado aceptado contestar, me desplaza hacia abajo para escribir acerca de su alcance y la dirección del espíritu de la pregunta. Debería haber adivinado que alguien lo hubiera hecho ya hace años. Esto está muy bien explicado y es el verdadero respuesta correcta.
  7. 5

    Intentar

    sed -n -e "/[0-9]/s/^[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*$/        /p"

    Tengo esto bajo cygwin:

    $ (echo "asdf"; \
       echo "1234"; \
       echo "asdf1234adsf1234asdf"; \
       echo "1m2m3m4m5m6m7m8m9m0m1m2m3m4m5m6m7m8m9") | \
      sed -n -e "/[0-9]/s/^[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\)[^0-9]*\([0-9]*\).*$/        /p"
    
    1234
    1234 1234
    1 2 3 4 5 6 7 8 9
    $
  8. 2

    No es lo que el OP solicitado (grupos de captura), pero usted puede extraer los números a través de:

    S='This is a sample 123 text and some 987 numbers'
    echo "$S" | sed 's//\n/g' | sed -r '/([0-9]+)/!d'

    Da lo siguiente:

    123
    987

Dejar respuesta

Please enter your comment!
Please enter your name here