Directo al punto, me pregunto cómo utilizar grep/buscar/sed/awk para que coincidan con una determinada cadena (que termina con un número) y el incremento de ese número por 1. Lo más cercano que he llegado es concatenar un 1 al final (que funciona bastante bien) porque el punto principal es simplemente cambiar el valor. Esto es lo que estoy haciendo actualmente:

find . -type f | xargs sed -i 's/\(\?cache_version\=[0-9]\+\)//g'

Ya que yo no podía entender cómo incrementar el número, he capturado la totalidad de la cosa y sólo se anexa un «1». Antes, he tenido algo como esto:

find . -type f | xargs sed -i 's/\?cache_version\=\([0-9]\+\)/?cache_version=/g'

Por lo que al menos yo entiendo cómo captar lo que necesito.

Vez de explicar lo que esto es para, voy a explicar lo que yo quiero hacer. Se debe buscar texto en un archivo, de forma recursiva, con base en el directorio actual (no es importante, podría ser cualquier directorio, así que me gustaría que configurar más tarde), que coincide con «?cache_version=» con un número. Se va a incrementar el número y reemplazar el archivo.

Actualmente las cosas que tengo encima funciona, es sólo que no puedo incremento que encontró número al final. Sería agradable ser capaz de incrementar en lugar de anexar un «1», de manera que los valores futuros de no ser «11», «111», «1111», «11111», y así sucesivamente.

He ido a través de docenas de artículos/explicaciones, y, a menudo, la sugerencia es usar awk, pero no puedo por la vida de la combinación de ellos. Lo más cercano que se refiere a la utilización awk, que en realidad no reemplazar nada, es:

grep -Pro '(?<=\?cache_version=)[0-9]+' . | awk -F: '{ print "match is", $2+1 }'

Me pregunto si hay alguna manera para canalizar una sed al final y pasar el nombre del archivo original para que sed puede tener el nombre de archivo y se incrementa el número (de la awk), o lo que sea que necesita que xargs ha.

Técnicamente, este número no tiene ninguna importancia; esta sustitución es principalmente para asegurarse de que hay un nuevo número de teléfono, 100% seguro distinto a la última. Así que mientras estaba escribiendo esta pregunta, me di cuenta de que yo podría utilizar el sistema de tiempo – segundos desde la época (la técnica que se utiliza a menudo por AJAX para eliminar el almacenamiento en caché para su posterior «idéntica» de solicitudes). Terminé con esto, y me parece perfecto:

CXREPLACETIME=`date +%s`; find . -type f | xargs sed -i "s/\(\?cache_version\=\)[0-9]\+/$CXREPLACETIME/g"

(Yo almacenar el valor primero para todos los archivos de obtener el mismo valor, en caso de que ésta se extiende por varios segundos, por el motivo que sea)

Pero yo todavía amo a conocer a la pregunta original, en el incremento de un sólo número. Supongo que una solución fácil sería hacer un script en bash, pero aún así, yo pensaba que sería una forma más fácil de bucle a través de todos los archivos de forma recursiva y la comprobación de su contenido para un partido, a continuación, reemplazar, ya que es simplemente el incremento de un igualado número…no mucho más lógica. No quiero escribir para otros archivos o algo así – debe hacerlo en su lugar, como sed hace con el «yo» opción.

InformationsquelleAutor Ian | 2013-01-15

4 Comentarios

  1. 53

    Creo que encontrar el archivo no es la parte difícil para usted. Por tanto, me acaba de ir al grano, para hacer el +1 de cálculo. Si usted tiene gnu sed, se podría hacer de esta manera:

    sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "$((+1))"/ge' file

    vamos a tomar un ejemplo:

    kent$  cat test 
    ello
    barbaz?cache_version=3fooooo
    bye
    
    kent$  sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "$((+1))"/ge' test     
    ello                                                                             
    barbaz?cache_version=4fooooo
    bye

    se podría añadir la opción-i si te gusta.

    editar

    /e permite pasar igualado parte externa de comando, y hacer que la sustitución con el resultado de la ejecución. Gnu sed sólo.

    vea este ejemplo: comando externo/herramienta echo, bc se utilizan

    kent$  echo "result:3*3"|sed -r 's/(result:)(.*)/echo $(echo ""\|bc)/ge'       

    da de salida:

    result:9

    puede usar otro poderoso comando externo, como cortar, sed (de nuevo), awk…

    • Tienes razón que el hallazgo de los archivos no es la parte difícil, así que gracias por centrarse en el reemplazo de la parte. Yo sólo sé que algunas de las soluciones (tal vez usando awk lugar) no son capaces de utilizar find, posiblemente lo que es «duro» para encontrar los archivos. Pero esta solución parece muy prometedor. Así que la principal diferencia que veo es el -r opción y, a continuación, el $((\3+1)) en la reemplace. ¿El -r habilitar esta funcionalidad? De todos modos, voy a tratar de esto con find y la -i opción para sed y darte a conocer. Gracias!
    • Lo siento, también se dio cuenta de la echo y /e bandera. Puede usted explicar más acerca de los así?
    • ver editar en respuesta
    • Gracias por la actualización! Bien, así que tengan paciencia conmigo. Estoy bastante seguro de que esto funcionará. Pero me estoy encontrando con un problema. Puedo hacer lo mismo que tú, pero desde mis archivos contienen caracteres especiales, bash se queja acerca de la < carácter que hay un error de sintaxis cerca de la testigo inesperado. Cuando me sacarlos, entonces funciona como un ejemplo. Pero también, otros caracteres especiales como " (tal vez eso es todo, no en el resultado. Cuando agrego en -i, funciona, pero se elimina el " (y no funciona con < y posiblemente otros personajes). Hay algo más necesario con la echo parte?
    • Por cierto, aquí es lo que estoy usando: find . -type f | xargs sed -i -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo \1\2$((\3+1))\4/ge'. Y un ejemplo de una línea en los archivos es <script type="text/javascript" src="asdf.js?cache_version=2"></script>
    • Alguna idea sobre esto?
    • ¿cuál es el problema
    • Si el texto/línea en el archivo de texto es algo así como <script type="text/javascript" src="asdf.js?cache_version=2"></script>, luego me sale un error acerca de syntax error near the unexpected token "<". Y luego también, elimina " personajes (tal vez más). Dos comentarios de arriba contiene mi actual comando que hace esto. ¿Que sentido?
    • usted necesita para envolver la parte de eco con comillas dobles, como este: sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "\1\2$((\3+1))\4"/ge'
    • Ahh veo. Juro que lo hice. Bueno, que corrige el «<» carácter problema. Ahora el único problema es que el " están siendo eliminados al escribir en el archivo. ¿Sabes lo que podría hacer que eso suceda? Tal vez es sólo una -i problema, pero es raro. Hay " antes, pero ahora se ha ido después de que el script se ejecute
    • oh, lo siento, no aviso de la cita. a continuación, sucio&solución rápida: ...|sed 's/"/\\"/g'|sed -r 's/(.*)(\?cache_version=)([0-9]+)(.*)/echo "\1\2$((\3+1))\4"/ge'
    • Bien, es tan cerca! Así que terminé usando este: find . -type f | xargs sed -i -r 's/"/\\"/g;s/(.*)(cacheholder)([0-9]+)(.*)/echo "\1\2$((\3+1))\4"/ge' ya que la tubería no parecen funcionar. Y he probado en la línea de texto que les mostré anteriormente. Que trabajado. Luego he añadido en cada posible carácter especial en el teclado. Que trabajado. Entonces me di cuenta de que me olvidé " en el medio del texto. Cuando añadí que, se sustituye el " con \". Así que me gustaría tener a mi <script type=... línea, a continuación, un par de líneas más abajo, han "Some quote or whatever" y que vendría a sustituir con \"Some quote or whatever\".
    • Así funciona bien cuando el principal comparador partidos y contiene un ", pero el resto del texto no parecen querer. Supongo que es porque estoy sustituir cada ocurrencia de " con \" no importa lo que, antes de hacer el real de buscar/reemplazar. Hmmm
    • El primer ejemplo no funciona para mí. Estoy usando sed (GNU sed) 4.4 en Cygwin, pero no veo por qué sería un problema. Con -i cambia el número 24 en lugar de 4. Sin -i no estoy seguro de lo que hace, ya que el resultado es extraño, sólo se muestra la última línea. Tal vez que puede ser culpa de mi terminal. Pero en un servidor linux (GNU sed version 4.2.1), que funciona como se espera. El segundo ejemplo funciona en ambos sistemas.
    • Para mí no fue a trabajar con -r, pero funcionó sin -r. Raro. Estoy usando Git Bash para windows.
    • lo siento @LoMaPh no tengo máquina windows a prueba. todos los ejemplos en la respuesta anterior fueron probados en mi Linux. No puedo decir la diferencia entre git bash y bash, ya sea..

  2. 8

    Puro sed versión:

    Esta versión no tiene dependencias en otros comandos o las variables de entorno.
    Utiliza explícito de llevar. Para llevar a puedo usar el sí[email protected], pero otro nombre se puede utilizar si lo desea. Usar algo que no está presente en el archivo de entrada.
    Primero que encuentra SEARCHSTRING<number> y agrega un @ a ella.
    Se repite el incremento de los dígitos que tienen una pendiente de llevar (que es, tiene derecho a llevar el símbolo después de ella: [0-9]@)
    Si 9 se incrementa, este incremento de los rendimientos de un acarreo de sí mismo, y el proceso se repite hasta que ya no hay más pendientes lleva.
    Por último, lleva a que se dio, pero no se agrega a un dígito sin embargo, son reemplazados por 1.

    sed "s/SEARCHSTRING[0-9]*[0-9]/&@/g;:a {s/[email protected]/1/g;s/[email protected]/2/g;s/[email protected]/3/g;s/[email protected]/4/g;s/[email protected]/5/g;s/[email protected]/6/g;s/[email protected]/7/g;s/[email protected]/8/g;s/[email protected]/9/g;s/[email protected]/@0/g;t a};s/@/1/g" numbers.txt
    • Buena solución. No reemplazar @ símbolos parece que funciona reemplazando @ con otro, el menos común de símbolos tales como £: sed «s/cache_version=[0-9]*[0-9]/&£/g;:a {s/0£/1/g;s/1£/2/g;s/2£/3/g;s/3£/4/g;s/4£/5/g;s/5£/6/g;s/6£/7/g;s/7£/8/g;s/8£/9/g;s/9£/£0/g, t};s/£/1/g» $1
    • Tenga en cuenta que en MacOS el nombre de la etiqueta termina en una nueva línea, así que usted tiene que dividir el comando a través de dos líneas para que funcione.
  3. 7

    Este perl comando buscará todos los archivos en el directorio actual (sin atravesar, necesitará File::Find módulo o similar para que la tarea más compleja) y se incrementará el número de una línea que coincide con cache_version=. Utiliza el /e bandera de la expresión regular que se evalúa el reemplazo de la parte.

    perl -i.bak -lpe 'BEGIN { sub inc { my ($num) = @_; ++$num } } s/(cache_version=)(\d+)/$1 . (inc($2))/eg' *

    He probado con file en el directorio actual con los datos siguientes:

    hello
    cache_version=3
    bye

    Que las copias de seguridad del archivo original (ls -1):

    file
    file.bak

    Y file ahora con:

    hello
    cache_version=4
    bye

    Espero que pueda ser de utilidad para lo que usted está buscando.


    ACTUALIZACIÓN utilizar File::Find para recorrer los directorios. Se acepta * como argumento, pero para descartarlos con aquellos que se encuentran con File::Find. El directorio de comenzar la búsqueda es la corriente de la ejecución de la secuencia de comandos. Es codificados en la línea de find( \&wanted, "." ).

    perl -MFile::Find -i.bak -lpe '
    
        BEGIN { 
            sub inc { 
                my ($num) = @_; 
                ++$num 
            }
    
            sub wanted {
                if ( -f && ! -l ) {  
                    push @ARGV, $File::Find::name;
                }
            }
    
            @ARGV = ();
            find( \&wanted, "." );
        }
    
        s/(cache_version=)(\d+)/$1 . (inc($2))/eg
    
    ' *
    • File::Find es un módulo principal sólo para tu información.
    • Esta es sin duda útil! Yo no estaba buscando para Perl, pero bueno, si funciona, no puedo quejarme. Es allí cualquier manera que usted puede incluir cómo utilizar Find::File por lo que se busca de forma recursiva un directorio? Y si no quiero una copia de seguridad, debe acabo de quitar -i.bak? Gracias por la ayuda!
    • He actualizado la respuesta con una secuencia de comandos que atraviesan los directorios de búsqueda de la cadena en todos los archivos regulares y modificación de ellos la creación de un archivo de copia de seguridad. Uso -i sin extensión (como perl -MFile::Find -i -lpe ...) para modificar en su lugar, pero podría ser un poco arriesgado.
    • Prefiero perl sobre Gnu sed porque es pre-instalado en el Mac.
  4. 3

    Esta es feo (estoy un poco oxidado), pero aquí empieza el uso de sed:

    orig="something1" ;
    text=`echo $orig | sed "s/\([^0-9]*\)\([0-9]*\)//"` ;
    num=`echo $orig | sed "s/\([^0-9]*\)\([0-9]*\)//"` ;
    echo $text$(($num + 1))

    Con un nombre de archivo original ($orig) de «something1», sed divide el texto y numéricos partes en $text y $num, luego estas se combinan en la sección final con un número incrementado, lo que resulta en something2.

    Sólo el comienzo, ya que no considera los casos con números dentro del archivo de nombre o nombres con ningún número al final, pero espero que le ayuda con su objetivo original de la utilización de sed.

    Esto puede ser simplificado dentro de sed por el uso de tampones, yo creo (sed puede operar de forma recursiva), pero estoy realmente oxidado con ese aspecto de ella.

    • Hmmm … re-leer tu pregunta creo que no he contestado, pero esperemos que no, al menos algo útil en ella. Yo creo que he hecho algo esencialmente gusta lo que estás haciendo, completamente en el sed, pero por desgracia, no tenemos que la solución a la mano ahora mismo.
    • Tienes razón que no es exactamente lo que usted está buscando, pero se trata de la idea de derecho y está definitivamente en el camino correcto. Espero que sea bueno, pero me separé de las líneas para que yo pudiera leer mejor. Tengo un par de preguntas y/o comentarios, así que esto podría abarcar varios comentarios. Muy rápido – ¿por qué escapar de la `? Realmente no estoy mirando de hacer el de buscar/reemplazar en un nombre de archivo, pero en el contenido del archivo. Es por eso que en el OP, tiene la find comando y la canalización de los resultados para sed. Así que, como dije en el OP, si hay una manera de hacer un script en bash que utiliza la lógica que tiene, pero
    • modifica los archivos de contenido en su sitio, entonces esto realmente puede ayudar. Si usted tiene alguna idea sobre cómo combinarlos para hacer ambas cosas. Su última línea de código es lo que necesito, sólo dentro de reemplazar parte de sed. Pero la separación de estas cosas en distintas declaraciones como las que usted tiene el tipo de derrotas lo que necesito. Estoy pensando en usar find, entonces el bucle a través de los resultados, a continuación, utilizando la lógica y un final sed -i verdaderamente reemplazando el valor…pero no estoy seguro de si funciona de esa manera. ¿Sabe usted a qué me refiero? Gracias por la ayuda, aunque!
    • El escape de la backtick era sólo para mostrar en el post, ya que el carácter es también utilizado para la definición de los bloques de código aquí – en realidad no es la de escape (y yo tenemos inadvertidamente doble escape o algo). Yo creo que lo que propones es posible con sed-i, el uso de algunos de sed características más avanzadas. No estoy seguro de si el bash funciones matemáticas funciona completamente dentro de sed, sin embargo, por lo que usted puede ser que necesite una más elaborada «reemplazar [0-8] con [1-9], reemplace [9] con [10]» o algo así. Veo a un número de éxitos en «la matemática en el sed», pero parece que en su mayoría dicen, «trate de awk o perl en su lugar».
    • He quitado el escape por lo que ahora se muestra correctamente.
    • Ahhh bueno, no puedo creer que yo no he puesto que juntos y recordar ` es el código y podría ser el problema. Yo no estaba seguro de si había una razón especial con bash o algo. Así que no saben nada acerca de awk, ¿lo harías? La otra respuesta con sed aquí es bastante estrecha, y la respuesta con perl aquí es así. Parece lógico que alguien intente esto con awk 🙂
    • Tengo muy poca experiencia con awk, sobre todo, por el acaparamiento de los campos de los archivos de registro que me gustaría, a continuación, pasar a través de la sed para manipular. Lo he utilizado con tan poca frecuencia que siempre tengo que buscar o tomar un libro para recordar el formato adecuado. Lo siento.

Dejar respuesta

Please enter your comment!
Please enter your name here