linux - test - El código de retorno de sed no coincide
json filter online (6)
A continuación se muestra el patrón que usamos con sed -rn
o sed -r
.
El comando completo de búsqueda y reemplazo ("s / ... / ... / ...") es opcional. Si se utiliza la búsqueda y el reemplazo, para obtener mayor velocidad y haber coincidido con $ matchRe, usamos el valor más rápido posible de $ searchRe, utilizando. donde el personaje no necesita ser re-verificado y. {$ len} para secciones de longitud fija del patrón.
El valor de retorno para ninguno encontrado es $ notFoundExit.
/$matchRe/{s/$searchRe/$replacement/$options; Q}; q$notFoundExit
Por las siguientes razones:
- No se desperdicia tiempo probando para casos coincidentes y sin igual
- No hay pérdida de tiempo en copiar hacia o desde los almacenamientos intermedios
- Sin ramas superfluas
- Flexibilidad razonable
La variación del caso de los comandos Q variará el comportamiento dependiendo de cuándo se producirá la salida. Los comportamientos que implican la aplicación de la lógica booleana a una entrada de línea múltiple requieren más complejidad en la solución.
Estoy usando sed
para actualizar mi archivo de configuración json en el tiempo de ejecución. A veces, cuando el patrón no coincide en el archivo json, todavía sed
sale con el código de retorno 0.
Devolver 0 significa completar con éxito, pero ¿por qué sed
devuelve 0 si no encuentra el patrón adecuado y actualiza el archivo? ¿Hay alguna solución para eso?
¡Gracias!
Como ya sabemos, cuando sed no puede coincidir, simplemente devuelve su cadena de entrada, no se ha producido ningún error. Es cierto que una diferencia entre las cadenas de entrada y de salida implica una coincidencia, pero una coincidencia no implica una diferencia en las cadenas; después de todo sed podría simplemente haber coincidido con todos los caracteres de entrada. La falla se crea en el siguiente ejemplo
h=$(echo "$g" | sed ''s/.*/(abc[[:digit:]]/).*//1/g'')
if [ ! "$h" = "$g" ]; then
echo "1"
else
echo "2"
fi
donde g=Xabc1
da 1, mientras que el ajuste g=abc1
da 2; sin embargo, ambas cadenas de entrada se corresponden con sed. Por lo tanto, puede ser difícil determinar si sed se corresponde o no. Una solución:
h=$(echo "fix${g}ed" | sed ''s/.*/(abc[[:digit:]]/).*//1/g'')
if [ ! "$h" = "fix${g}ed" ]; then
echo "1"
else
echo "2"
fi
en cuyo caso, el 1 se imprime if-and-only-si sed ha coincidido.
Estas respuestas son muy complicadas. ¿Qué hay de malo en escribir un poco de script de shell que use grep para averiguar si lo que desea reemplazar está allí y luego usar sed para reemplazarlo?
grep -q $TARGET_STRING $file
if [ $? -eq 0 ]
then
echo "$file contains the old site"
sed -e "s|${TARGET_STRING}|${NEW_STRING}|g" ....
fi
Esto podría funcionar para usted (GNU sed):
sed ''/search-string/{s//replacement-string/;h};${x;/./{x;q0};x;q1}'' file
Si se encuentra la search-string
, se reemplazará con replacement-string
y al final del archivo sed
saldrá con 0
código de retorno. Si no se realiza ninguna sustitución, el código de retorno será 1
.
Una explicación más detallada:
En sed, el usuario tiene dos registros a su disposición: el espacio de patrón (PS) en el que se carga la línea actual (menos el salto de línea) y un registro de reserva llamado espacio de espera (HS) que está inicialmente vacío.
La idea general es usar el HS como una bandera para indicar si se ha producido una sustitución. Si el HS todavía está vacío al final del archivo, no se han realizado cambios, de lo contrario se han producido cambios.
El comando /search-string/
coincide con search-string
con lo que está en el PS y si se encuentra que contiene el search-string
se ejecutan los comandos entre los siguientes llaves.
En primer lugar, la sustitución s//replacement-string/
(sed utiliza la última expresión regular, es decir, la search-string
, si la parte izquierda está vacía, por lo que s//replacement-string
es igual a s/search-string/replacement-string/
) y luego de esto, el comando h
hace una copia del PS y lo coloca en el HS.
El comando $
sed se usa para reconocer la última línea de un archivo y luego ocurre lo siguiente.
Primero, el comando x
intercambia los dos registros, por lo que el HS se convierte en el PS y el PS en el HS.
Luego se busca el PS por cualquier carácter /./
( .
Significa que coincide con cualquier carácter) recuerde que el HS (ahora el PS) estaba inicialmente vacío hasta que se produjo una sustitución. Si la condición es verdadera, la x
se ejecuta nuevamente, seguida del comando q0
que finaliza todo el procesamiento sed y establece el código de retorno en 0
. De lo contrario, se ejecuta el comando x
y el código de retorno se establece en 1
.
NB, aunque q
deja de procesar sed, no impide que el PS se reensamble por sed y se imprima como de costumbre.
Otra alternativa:
sed ''/search-string/!ba;s//replacement-string/;h;:a;$!b;p;x;/./Q;Q1'' file
o:
sed ''/search-string/,${s//replacement-string/;b};$q1'' file
Quise truncar un archivo al salir cuando se encontró la coincidencia (y excluir la línea correspondiente). Esto es útil cuando un proceso que agrega líneas al final del archivo puede volver a ejecutarse. "Q; Q1" no funcionó, pero simplemente "Q1" lo hizo, de la siguiente manera:
si sed -i ''/ text Yo quería encontrar / Q1'' file.txt luego inserte una línea en blanco al final del archivo + nuevas líneas fi inserte solo las líneas nuevas sin la línea en blanco
como comentó @cnicutar, el código de retorno de un comando significa que el comando se ejecutó con éxito. no tiene nada que ver con la lógica que implementó en los códigos / scripts.
entonces si tienes:
echo "foo"|sed ''/bar/ s/a/b/''
sed devolverá 0
pero si escribe algunos errores de sintaxis / expresión, o la entrada / archivo no existe, sed no puede ejecutar su solicitud, sed devolverá 1.
solución alternativa
esto en realidad no es una solución . sed tiene el comando q
: (desde la página man):
q [exit-code]
aquí puede definir el código de salida como lo desee. Por ejemplo ''/foo/!{q100}; {s/f/b/}''
''/foo/!{q100}; {s/f/b/}''
saldrá con el código 100 si foo
no está presente, y de lo contrario realizará la sustitución f-> b y saldrá con el código 0.
Caja emparejada:
kent$ echo "foo" | sed ''/foo/!{q100}; {s/f/b/}''
boo
kent$ echo $?
0
Caso sin igual:
kent$ echo "trash" | sed ''/foo/!{q100}; {s/f/b/}''
trash
kent$ echo $?
100
Espero que esto responda tu pregunta.
editar
Debo agregar que, el ejemplo anterior es solo para el procesamiento de una línea. No sé tu requerimiento exacto. cuando quieras obtener la exit 1
. una línea sin igual o el archivo completo. Si todo el archivo no coincide con el caso, puede considerar awk, o incluso hacer un grep
antes de su procesamiento de texto ...