Quiero reemplazar solo las primeras kinstancias de una palabra.
¿Cómo puedo hacer esto?
P.ej. Dicho archivo foo.txtcontiene 100 instancias de la palabra 'linux'.
Necesito reemplazar las primeras 50 ocurrencias solamente.
text-processing
sed
awk
narendra-choudhary
fuente
fuente

Respuestas:
La primera sección a continuación describe el uso
sedpara cambiar las primeras k-ocurrencias en una línea. La segunda sección amplía este enfoque para cambiar solo las primeras k-ocurrencias en un archivo, independientemente de en qué línea aparezcan.Solución orientada a líneas
Con sed estándar, hay un comando para reemplazar la k-ésima aparición de una palabra en una línea. Si
kes 3, por ejemplo:O bien, uno puede reemplazar todas las ocurrencias con:
Ninguno de estos es lo que quieres.
GNU
sedofrece una extensión que cambiará la k-ésima ocurrencia y todo después de eso. Si k es 3, por ejemplo:Estos se pueden combinar para hacer lo que quieras. Para cambiar las 3 primeras ocurrencias:
donde
\nes útil aquí porque podemos estar seguros de que nunca ocurre en una línea.Explicación:
Utilizamos tres
sedcomandos de sustitución:s/\<old\>/\n/g4Esta es la extensión GNU para reemplazar el cuarto y todos los sucesos posteriores de
oldcon\n.La función de expresión regular extendida
\<se usa para hacer coincidir el comienzo de una palabra y\>para hacer coincidir el final de una palabra. Esto asegura que solo las palabras completas coincidan. La expresión regular extendida requiere la-Eopciónsed.s/\<old\>/new/gSolo quedan las tres primeras ocurrencias
oldy esto las reemplaza a todasnew.s/\n/old/gEl cuarto y todos los sucesos restantes de
oldfueron reemplazados por\nen el primer paso. Esto los devuelve a su estado original.Solución no GNU
Si GNU sed no está disponible y desea cambiar las primeras 3 apariciones de
oldanew, utilice tresscomandos:Esto funciona bien cuando
kes un número pequeño pero se escala deficiente a grandek.Dado que algunos seds que no son GNU no admiten la combinación de comandos con punto y coma, cada comando aquí se presenta con su propia
-eopción. También puede ser necesario verificar quesedadmite los símbolos de límite de palabras,\<y\>.Solución orientada a archivos
Podemos decirle a sed que lea todo el archivo y luego realice las sustituciones. Por ejemplo, para reemplazar las tres primeras ocurrencias del
olduso de un sed de estilo BSD:Los comandos sed
H;1h;$!d;xleen todo el archivo.Como lo anterior no utiliza ninguna extensión GNU, debería funcionar en sed BSD (OSX). Tenga en cuenta, pensó, que este enfoque requiere un
sedque puede manejar largas colas. GNUseddebería estar bien. Aquellos que usan una versión de GNU noseddeben probar su capacidad para manejar largas colas.Con un GNU sed, podemos usar el
gtruco descrito anteriormente, pero con\nreemplazado por\x00, para reemplazar los primeros tres casos:Este enfoque se escala bien y se
khace grande. Sin embargo, esto\x00supone que no está en su cadena original. Dado que es imposible poner el carácter\x00en una cadena bash, esto generalmente es una suposición segura.fuente
tr '\n' '|' < input_file | sed …. Pero, por supuesto, eso convierte toda la entrada en una línea, y algunos seds que no son GNU no pueden manejar líneas arbitrariamente largas. (2) Usted dice: "... arriba, la cadena entre comillas'|'debe reemplazarse por cualquier carácter, o cadena de caracteres, ..." Pero no puede usartrpara reemplazar un carácter con una cadena (de longitud> 1). (3) En tu último ejemplo, dices-e 's/\<old\>/new/' -e 's/\<old\>/w/' | tr '\000' '\n'\>/new. Esto parece ser un error tipográfico para-e 's/\<old\>/new/' -e 's/\<old\>/new/' -e 's/\<old\>/new/' | tr '\000' '\n'.Usando Awk
Los comandos awk se pueden usar para reemplazar las primeras N apariciones de la palabra con el reemplazo.
Los comandos solo reemplazarán si la palabra es una coincidencia completa.
En los ejemplos a continuación, estoy reemplazando las primeras
27apariciones deoldconnewUsando sub
Reemplazar el campo manualmente
Realizar un chequeo antes
RESULTADOS
P.ej
a
fuente
$ibit, ha sido editado, gracias :)Supongamos que desea reemplazar solo las primeras tres instancias de una cadena ...
nota: lo anterior probablemente no funcionará con comentarios incrustados
... o en mi caso de ejemplo, de un '1' ...
SALIDA:
Allí uso dos técnicas notables. En primer lugar, cada aparición de
1una línea se reemplaza por\n1. De esta manera, como hago los reemplazos recursivos a continuación, puedo estar seguro de no reemplazar la ocurrencia dos veces si mi cadena de reemplazo contiene mi cadena de reemplazo. Por ejemplo, si lo reemplazoheconheyél, aún funcionará.Hago esto como:
En segundo lugar, estoy contando los reemplazos agregando un personaje al
hespacio antiguo para cada ocurrencia. Una vez que llegue a tres, no ocurrirán más. Si aplica esto a sus datos y cambia los\{3\}reemplazos totales que desea y las/\n1/direcciones a lo que quiera reemplazar, debe reemplazar solo los que desee.Solo hice todas las
-ecosas para facilitar la lectura. POSIXly Podría escribirse así:Y con GNU
sed:Recuerde también que
sedestá orientado a líneas: no se lee en todo el archivo y luego intenta volver a recorrerlo, como suele ser el caso en otros editores.sedEs simple y eficiente. Dicho esto, a menudo es conveniente hacer algo como lo siguiente:Aquí hay una pequeña función de shell que lo agrupa en un comando simplemente ejecutado:
Entonces con eso puedo hacer:
...y obten...
...o...
...Llegar...
... o, para que coincida con su ejemplo (en un orden de magnitud menor) :
fuente
Una alternativa corta en Perl:
Cambie el valor de `$ n $ a su gusto.
Cómo funciona:
newporold(s/old/new/) y siempre que se pueda, se incrementa la variable$i(++$i).1 while ...) siempre y cuando haya realizado menos$nsustituciones en total y puede realizar al menos una sustitución en esa línea.fuente
Use un bucle de concha y
ex!Sí, es un poco tonto.
;)
Nota: Esto puede fallar si hay menos de 50 instancias
olden el archivo. (No lo he probado). Si es así, dejaría el archivo sin modificar.Mejor aún, usa Vim.
Explicación:
fuente
Una solución simple pero no muy rápida es recorrer los comandos descritos en /programming/148451/how-to-use-sed-to-replace-only-the-first-occurrence-in-a -archivo
Este comando sed en particular probablemente solo funcione para GNU sed y si newword no es parte de oldword . Para sed no GNU, vea aquí cómo reemplazar solo el primer patrón en un archivo.
fuente
Con GNU
awkpuede establecer el separador de registrosRSpara la palabra que se reemplazará delimitada por límites de palabras. Entonces se trata de establecer el separador de registros en la salida a la palabra de reemplazo para los primeroskregistros mientras se conserva el separador de registros original para el restoO
fuente