Estoy tratando de 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 que la búsqueda no distinga entre mayúsculas y minúsculas. Por lo que busqué en Google, parece que agregar i
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é va mal aquí y cómo lo soluciono?
macos
replace
sed
case-insensitive
Craig Walker
fuente
fuente
I
es una extensión GNU que puede no estar disponible con su copia de sed.man sed
ES coherente con la implementación: no se menciona (y no se admite en la práctica) la coincidencia que no distingue entre mayúsculas y minúsculas; Si encuentra algún documento que indique lo contrario, háganoslo saber.g
prefijo, por lo que puedo usargsed
ogdate
cuando necesito una función que no se encuentra en la versión estándar.Respuestas:
Para ser claros: en macOS , a partir de Mojave (10.14),
sed
que es la implementación de BSD , NO admite la coincidencia que no distingue entre mayúsculas y minúsculas , es difícil de creer, pero es cierto. La respuesta aceptada anteriormente , que en sí misma muestra un comando GNUsed
, ganó ese estado debido a laperl
solución basada en la mencionada en los comentarios.Para que la solución Perl también funcione con caracteres extranjeros , a través de UTF-8, use algo como:
-C
activa la compatibilidad con UTF-8 para transmisiones y archivos, asumiendo 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 pasada a-pe
) - este es el equivalente más corto del más detallado-e 'use utf8;'.
Gracias, Mark Reed(Tenga en cuenta que el uso
awk
tampoco es una opción , ya queawk
en macOS (es decir, BWK awk , también conocido como BSD awk ) parece desconocer por completo las configuraciones regionales: sus funcionestolower()
ytoupper()
ignoran los caracteres extranjeros (ysub()
/gsub()
no tienen indicadores que no distingan entre mayúsculas y minúsculas para empezar con).)fuente
Nota del editor : esta solución no funciona en macOS (lista para usar), porque solo se aplica a GNU
sed
, mientras que macOS viene con BSDsed
.Escriba con mayúscula la "I".
fuente
I
sufijo no es un uso portátil desed
. POSIXsed
usa solo Expresiones regulares básicas (BRE), que son sorprendentemente limitadas. Ni siquiera admiten+
(tienes que usar\{1,\}
en su lugar), y mucho menos la coincidencia que no distingue entre mayúsculas y minúsculas. La única forma portátil de hacerlo con sed es buscar algo como/[hH][eE][lL][lL][oO]/
, que a menudo no será práctico./gI
contrario, solo funcionará en el primer partido.Otra solución alternativa para
sed
Mac OS X es instalargsed
desde MacPorts o HomeBrew y luego crear el aliassed='gsed'
.fuente
brew install gnu-sed
luego fue a mi ~ / .bash_profile y agregué el alias. Gracias @davmatbrew install gnu-sed --with-default-names
: esto anulará el valor predeterminadosed
.Las preguntas frecuentes de sed abordan la búsqueda que no distingue entre mayúsculas y minúsculas . Señala que a) muchas versiones de sed admiten una bandera para él yb) es incómodo hacerlo en sed, debería usar awk o Perl.
Pero para hacerlo en POSIX sed, sugieren tres opciones (adaptadas para sustitución aquí):
Convierta a mayúsculas y almacene la línea original en el espacio de espera; Sin embargo, esto no funcionará para sustituciones, ya que el contenido original se restaurará antes de imprimir, por lo que solo es bueno para insertar o agregar líneas basadas en una coincidencia que no distinga entre mayúsculas y minúsculas.
Tal vez las posibilidades se limitan a
FOO
,Foo
efoo
. Estos pueden ser cubiertos porPara buscar todas las coincidencias posibles, se pueden usar expresiones entre corchetes para cada carácter:
fuente
La versión para Mac
sed
parece un poco limitada. Una forma de evitar esto es usar un contenedor de Linux (a través de Docker) que tiene una versión utilizable desed
:fuente
Si primero está haciendo una coincidencia de patrones, por ejemplo,
entonces quieres poner el
I
después del patrón:Ejemplo:
devoluciones
willma
; sin elI
, devuelve la cadena sin tocar (Fred
).fuente
sed: 1: "/fred/Is//willma/g": invalid command code I
sed -r '/'"$PATTERN"'/I,${s//'$YELLOW'&'$NO_COLOR'/g;b};$q3'
. Imprime el texto y, si se encuentra un patrón (que no distingue entre mayúsculas y minúsculas), resalta el texto en amarillo (color ansi). Si no se encuentra, devuelve el código de salida 3.Tenía una necesidad similar y se me ocurrió esto:
este comando para simplemente encontrar todos los archivos:
este para excluir this_shell.sh (en caso de que pones el comando en un script llamado this_shell.sh ), envía la salida a la consola para ver qué sucedió, y luego usa sed en cada nombre de archivo encontrado para reemplazar el texto foo con bar :
Elegí este método, ya que no me gustó que se cambiaran todas las marcas de tiempo de los archivos no modificados. alimentar el resultado de grep permite ver solo 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. Es posible que no funcione en algunos entornos para archivos con espacios incrustados. (?)
fuente
Utilice lo siguiente para reemplazar todas las apariciones: sed 's / foo / bar / gI' mylog.txt
fuente
I
. Tampoco creo que esto realmente responda a la pregunta, ya que no se refiere al reemplazo global.