Dada la siguiente cadena, ¿cómo se puede reemplazar el 6 y el 7 por conseguir 14 y 15 dígitos usando awk o sed.

xxxxx02xxxxxx89xx
xxxxx22xxxxxx33xx

salida

xxxxx89xxxxxx89xx
xxxxx33xxxxxx33xx

Soy novato aquí, lo siento por mi pregunta.

InformationsquelleAutor MJM | 2014-09-01

4 Comentarios

  1. 3

    El comando sed es sencillo, pero difícil de leer:

    sed 's/\(.....\)..\(......\)\(..\)//'

    Posiblemente el más fácil de mantener solución puede ser tenido en Gnu awk (pero no otros awk variedades. Sin embargo, ver más abajo.):

    gawk -v FIELDWIDTHS="5 2 6 2 999" -v OFS='' '{$2=$4;print}'

    La FIELDWIDTHS variable define 5 de ancho fijo de campos: los primeros 5 caracteres, en los próximos dos personajes (posiciones 6 y 7); los próximos seis caracteres (8 a 13); las dos siguientes caracteres (14 y 15); y el próximo (a) 999 caracteres, que debe ser el resto de la línea. (Si usted tiene más líneas, aumente como sea necesario). Configuración de OFS para vaciar a menudo es útil con campos de longitud fija; evita awk de insertar espacios entre los campos en la salida.

    FIELDWIDTHS es un GNU awk extensión. Sin embargo, es bastante fácil reimplementar en Posix awk. He aquí una sencilla aplicación:

    function fieldwidth_set(         i) {
      if (PROCINFO["FS"]) FIELDWIDTHS = FIELDWIDTHS;
      else if (length(FIELDWIDTHS)) {
        _FW_NF = split(FIELDWIDTHS, _FW_ARRAY);
        for (i in _FW_ARRAY) {
          if (_FW_ARRAY[i] !~ /^[0-9]+$/) {
            printf "Illegal value '%s' in FIELDWIDTHS\n", _FW_ARRAY[i] >>"/dev/stderr";
            exit 1;
          }
          _FW_ARRAY[i]+=0;
        }
      } else
        _FW_NF = 0;
    }
    function set_fieldwidth(fw) { FIELDWIDTHS=fw; fieldwidth_set(); }
    function fw_(               a,i,k) {
      if (_FW_NF) {
        a = $0;
        $0 = "";
        k=1;
        for (i=1; i<=_FW_NF; ++i) { 
          $i = substr(a, k, _FW_ARRAY[i]);
          k+=_FW_ARRAY[i];
        }
      }
    }
    BEGIN{set_fieldwidth()}
    {fw_()}

    Que yo sepa, sólo Gnu awk permite mezclar archivos de programa y el texto del programa en el awk de la línea de comandos. Posix requiere que el -f program-file opción, que puede ser repetido, pero no requiere el -e program-text opción, como el implementado por Gnu awk. Por consiguiente, si desea utilizar el fragmento anterior con una línea de comando awk programa, usted necesita para hacer algo como esto:

    awk -v FIELDWIDTHS="5 2 6 2 999" -v OFS= -f fw.awk -f <(echo '{$2=$4;print}')

    (Suponiendo que poner el fieldwidth fragmento en fw.awk.)

    Para la eficiencia, fw.awk insiste en que le diga lo que usted ha cambiado FIELDWIDTHS llamando fieldwidth_set(). O usted puede utilizar set_fieldwidth("....") para establecer FIELDWIDTHS a un nuevo valor. Va a trabajar con GNU awk, así como con otros awk implementaciones; le permite a GNU awk hacer el trabajo pesado.

    • ¿Por qué haces ($2=$4)||1 en lugar de {$2=$4}1?
    • ¿Por qué no? Ninguna buena razón, aunque tengo una vaga y muy posiblemente incorrecta sensación de que se produce un poco mejor el código intermedio.
    • Me acaba de preguntar para saber si uno es mejor, más rápido, más robusto que los otros, no lo han visto hacer de esta manera. Sé que para asegurarse de que sólo el uso de '$2=$4' fallará si la entrada es 0
    • mi versión no admiten gawk comando
    • Hace un par de años tuvimos una bastante larga discusión entre los asiduos a comp.lang.awk acerca de construcciones como ($2=$4)||1 y el consenso fue que sólo se ofusca el código ya que es poner a una acción (la tarea) en el estado parte, pero, a continuación, agregar una segunda condición (||1) a fuerza de awk para ignorar el resultado de la asignación y no tiene ningún beneficio vs {$2=$4}1.
    • Justo lo suficiente. Pero el unobfuscated versión es de suponer que la {$2=$4;print}. Voy a cambiar un poco.
    • La ventaja de usar 1 supera a la mayor claridad de print en un pequeño script, ya que las unidades del hogar múltiple awk fundamentos simultáneamente: 1) que un script awk es hacer de <condition>{<action>} declaraciones, y 2) que el defecto <action> es para imprimir el registro actual. Todo el mundo NECESITA saber tanto de aquellos a utilizar awk efectivamente por lo que ya se hace y el significado de 1 que es obvio o no y tener que aprender lo que 1 no les enseña.
    • ¿Qué es exactamente el beneficio de {$2=$4}1? Que se ahorra cinco caracteres es sólo un beneficio para los golfistas. mawk, que no tiene un gran optimizador, pero no proporciona un mecanismo para volcar virtual de la ops, muestra que {$2=$4;print} a ser la más corta del programa compilado, por lo que es de suponer que la forma más rápida (y ($2=$4)||1 es el más largo, así que acepto la corrección).
    • No, el beneficio no es ni la brevedad ni el rendimiento, es precisamente las oportunidades de aprendizaje que he descrito en mi comentario.

  2. 2

    Usted podría intentar el siguiente comando sed,

    $ echo 'xxxxx03xxxxxx75xx' | sed -r 's/^(.{5})(..)(.{6})..//g' 
    xxxxx03xxxxxx03xx
    $ echo 'xxxxx03xxxxxx75xx' | sed  's/^\(.\{5\}\)\(..\)\(.\{6\}\)..//g'
    xxxxx03xxxxxx03xx

    Reemplaza 14 y 15 dígitos con los dígitos en la posición 6 y 7.

    $ echo 'xxxxx03xxxxxx75xx' | sed -r 's/^(.{5})..(.{6})(..)//g'
    xxxxx75xxxxxx75xx
    $ echo 'xxxxx03xxxxxx75xx' | sed 's/^\(.\{5\}\)..\(.\{6\}\)\(..\)//g'
    xxxxx75xxxxxx75xx

    Reemplaza 6 y 7 dígitos con los dígitos en la posición 14 y 15.

    • cómo si yo iba a hacer el procedimiento con más de un registro en un archivo?
    • sed los procesos de cada línea en el archivo de entrada
    • si hay más de dos 02 en la misma línea, a continuación, debe utilizar el indicador global para reemplazar tanto 02‘s con 89. sed y awk proceso de la línea de entrada de línea.
    • Lo siento si he confundido, a lo que me refiero es si tengo estos archivos:archivo1: xxxxx03xxxxxx75xx archivo2: xxxxx25xxxxxx12xx archivo3: xxxxx11xxxxxx00xx, ¿cómo puedo cambiar el 14 y 15 dígitos mediante la obtención de 6º y 7º dígito?
    • actualización de tu pregunta…
    • Hola, es posible en el sed?
    • sí, usted puede hacer esto mediante la ejecución de este comando sed en cada archivo por separado, sed -r 's/^(.{5})(..)(.{6})../\1\2\3\2/g' file
    • No veo cómo su solución de cambiar el digi en la posición 6 y 7 con el uno en la posición 14 y 15. how can I replace 6th and 7th by getting 14th and 15th digit using awk or sed.
    • actualizado..no veo la pregunta correctamente..
    • Puede quitar las cosas que no responde OPs solicitud.
    • Me da este error. sed: ilegal opción — r Uso: sed [-n] [-e script] [-f source_file] [archivo…]
    • su sed no apoyo -r parámetro. Así que trate de sed 's/^\(.\{5\}\)..\(.\{6\}\)\(..\)/\1\3\2\3/g' file
    • Funciona, gracias! ¿Y si quiero cambiar los días 14 y 15 dígitos 6 y 7 dígitos?
    • actualizado… Ver el segundo comando.

  3. 2

    Este debe seguir su solicitud y trabajar con todos los awk:

    awk '{$6=$14;$7=$15}1' FS= OFS= file
    xxxxx89xxxxxx89xx
    xxxxx33xxxxxx33xx

    Va a cambiar el dígito en la posición 6 por el uno en 14 y el uno en 7 con el int 15

    Si FS="" no funciona, intente esto:

    awk '{n=split($0,a,"");a[6]=a[14];a[7]=a[15];for (i=1;i<=n;i++) printf "%s",a[i];print ""}' input

    Como solicitud en uno de los comentarios:

    It works, thanks! How about if I want to replace 14th and 15th digit by 6th and 7th digit? – Vision111

    awk '{$14=$6;$15=$7}1' FS= OFS= file
    • Cuando me lo probé: awk ‘{$6=$14;$7=$15}1’ FS= OFS= ejemplo: salida: xxxxx27xxxxxx89xx xxxxx76xxxxxx72xx. Nada cambia
    • Es importante que hay un espacio después de OFS= en el primer ejemplo, o puede utilizar FS="" OFS="". Intente esto, a continuación,echo "xxxxx27xxxxxx89xx" | awk '{$6=$14;$7=$15}1' FS= OFS=. También puede probar este awk 'BEGIN {FS=OFS=""} {$6=$14;$7=$15}1' o este: awk -v FS="" -v OFS="" '{$6=$14;$7=$15}1'
    • He intentado de todo el código que usted ha proporcionado, pero eso no cambiaba el resultado. echo «xxxxx27xxxxxx89xx» | awk ‘{$6=$14;$7=$15}1’ FS= OFS= xxxxx27xxxxxx89xx
    • Usted tiene un espacio después de la multa =. A partir de este echo "xxxxx27xxxxxx89xx" | awk '{$6=$14;$7=$15}1' FS= OFS= , me sale: xxxxx89xxxxxx89xx. Esto es evidente awk y debería funcionar en la mayoría de los sistemas.
    • No sé por qué todavía no funcionó para mí
    • Esto sólo funcionará en GAWK
    • Por qué? Yo no veo nada especial con este que hacer gawk
    • Configuración de la FS y la OFS para nada no funciona de la misma manera, cuando no en GAWK. Intente ejecutar con el estándar UNIX awk o el uso de --compat.
    • Yo dod no sé. Puede que me apunte a alguna información por escrito acerca de esto?
    • He recreado en mi post original ya que parece que hay una diferencia en cómo la configuración de FS para nada funciona con una versión diferente de awk. ¿Qué OS está usted?
    • Esto no funciona cuando se Ejecuta con --posix aunque ?
    • Acepto la corrección, ajuste FS= ES un gawk extensión. Yo no tenía ni idea… Gracias.

  4. 1

    Esto va a funcionar sin GNU awk GAWK

    awk 'sub(/[0-9]+/,substr($0,14,2))' file

    O más, pero más genérico

    awk '{print substr($0,0,5) substr($0,14,2) substr($0,8)}' file

    RESULTADO:

    xxxxx89xxxxxx89xx
    xxxxx33xxxxxx33xx
    • la primera posición de carácter en una cadena es 1, no 0. Si el 1er carácter estaba en la posición 0, el 14 de personaje sería en la posición 13, no 14. Su primer substr() debe ser substr($0,1,5). Yo no uso el sub (a), ya que no hay nada que sugieren no puede ser un dígito en los primeros 5 caracteres o después de las 7 de uno.
    • Usted puede utilizar el 0 o el 1, no hace ninguna diferencia. Y sé que por eso he añadido la segunda solución.
    • Eso es como decir que se puede utilizar -157 o 1. Asegúrese de que usted va a obtener la subcadena que empieza en el 1, pero eso es porque eso es lo que substr() produce dado un subíndice que está fuera de rango, no porque sea válido subíndice de uso. Todo lo que hace su ofuscar su código. Imagine que usted necesita para imprimir el 1 de char y luego la 2ª char por separado – escritura substr($0,0,1); substr($0,2,1), no tendría ningún sentido igual que con el índice 0 para el 1 de char pero 14 para el 14 de char no aquí.
    • Bueno, la voy a usar 1 en el futuro 🙂

Dejar respuesta

Please enter your comment!
Please enter your name here