Búsqueda insensible a mayúsculas y sustitúyela por sed

Intento usar SED para extraer texto de un archivo de registro.

Puedo buscar y reemplazar sin demasiados problemas:

sed 's/foo/bar/' mylog.txt 

Sin embargo, quiero hacer que la búsqueda no distinga entre mayúsculas y minúsculas. De lo que he buscado en Google, parece que añadirlo al final del comando debería funcionar:

 sed 's/foo/bar/i' mylog.txt 

Sin embargo, esto me da un mensaje de error:

 sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i' 

¿Qué está mal aquí, y cómo lo soluciono?

Estoy en macOS, en caso de que importe.

Para ser claros: en macOS , a partir de Sierra (10.12), sed , que es la implementación de BSD , NO admite coincidencias que no distinguen entre mayúsculas y minúsculas , es difícil de creer, pero cierto. La respuesta aceptada anteriormente , que a su vez muestra un comando GNU sed , ganó ese estado debido a la solución basada en perl mencionada en los comentarios.

Para que esa solución de Perl funcione también con caracteres extranjeros , a través de UTF-8, use algo como:

 perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo" 
  • -C activa el soporte UTF-8 para transmisiones y archivos, suponiendo que la configuración regional actual está basada en UTF-8.
  • -Mutf8 le dice a Perl que interprete el código fuente como UTF-8 (en este caso, la cadena pasó a -pe ) – este es el equivalente más corto de la más -e 'use utf8;'. Gracias, Mark Reed

(Tenga en cuenta que el uso de awk tampoco es una opción , ya que awk en macOS (es decir, BWK awk , también conocido como BSD awk ) parece ser completamente ajeno a las configuraciones regionales; sus funciones tolower() y toupper() ignoran caracteres extraños (y sub() / gsub() no tienen indicadores de insensibilidad a mayúsculas / minúsculas para empezar).)

Capitalice el ‘yo’.

 sed 's/foo/bar/I' file 

Otra gsed para sed en Mac OS X es instalar gsed desde MacPorts o HomeBrew y luego crear el alias sed='gsed' .

La versión Mac de sed parece un poco limitada. Una forma de evitar esto es utilizar un contenedor de Linux (a través de Docker) que tiene una versión utilizable de sed :

 cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig' 

Las preguntas frecuentes de sed abordan la búsqueda estrechamente relacionada insensible a mayúsculas y minúsculas. Señala que a) muchas versiones de sed admiten una bandera para ello yb) es incómodo de hacer en sed, debería usar awk o Perl.

Pero para hacerlo en POSIX sed, sugieren tres opciones (adaptadas para la sustitución aquí):

  1. Convierte a mayúsculas y almacena la línea original en el espacio de espera; sin embargo, esto no funcionará para las sustituciones, ya que el contenido original se restaurará antes de la impresión, por lo que solo sirve para insertar o agregar líneas basadas en una coincidencia que no distingue entre mayúsculas y minúsculas.

  2. Tal vez las posibilidades se limitan a FOO , Foo y foo . Estos pueden ser cubiertos por

     s/FOO/bar/;s/[Ff]oo/bar/ 
  3. Para buscar todas las coincidencias posibles, se pueden usar expresiones de corchetes para cada personaje:

     s/[Ff][Oo][Oo]/bar/ 

Tenía una necesidad similar, y se me ocurrió esto:

este comando simplemente para encontrar todos los archivos:

 grep -i -l -r foo ./* 

este para excluir this_shell.sh (en caso de que ponga el comando en un script llamado this_shell.sh ), coloque el resultado en la consola para ver qué sucedió, y luego use sed en cada nombre de archivo que se encuentre para reemplazar el texto foo con barra :

 grep -i -l -r --exclude "this_shell.sh" foo ./* | tee /dev/fd/2 | while read -rx; do sed -b -i 's/foo/bar/gi' "$x"; done 

Elegí este método, ya que no me gusta tener todas las marcas de tiempo modificadas para los archivos no modificados. Al alimentar el resultado de grep, solo se pueden ver los archivos con el texto de destino (por lo tanto, es probable que también mejore el rendimiento / velocidad)

asegúrese de hacer una copia de seguridad de sus archivos y probarlos antes de usarlos. Puede no funcionar en algunos entornos para archivos con espacios integrados. (?)

Si está haciendo coincidencia de patrones primero, por ejemplo,

 /pattern/s/xx/yy/g 

entonces quieres poner el I después del patrón:

 /pattern/Is/xx/yy/g 

Ejemplo:

 echo Fred | sed '/fred/Is//willma/g' 

devuelve willma ; sin el I , devuelve la cadena intacta ( Fred ).

 sed 's/string1/string2/Ig' 

Capital I es una opción que es útil para buscar una cadena independientemente de la distinción entre mayúsculas y minúsculas.

    Intereting Posts