Tengo un archivo de nombres de usuario y contraseñas en formato JSON que quiero convertir para procesar.
He utilizado sed
diferentes comandos para procesarlo, pero lo que me gustaría saber es cómo agrupar los tres comandos en uno para el futuro.
Formato original
{ "user.name1" : "hashed_password",
"user.name2" : "hashed_password" }
Salida deseada
user.name:hashed_password
Estos son los comandos que ejecuté, sin embargo, no pude encadenarlos usando tuberías o simplemente concatenándolos donde aparece un error sed: -e expression #1, char 8: unknown option to 's'
.
Comando ofensivo...
sed -i 's/\"//g/s/\,/\n/g/\s//g' input_file
sed: -e expression #1, char 8: unknown option to `s'
¿Cómo se podrían concatenar los siguientes comandos en uno solo?
Comandos Eliminar comillas dobles
sed -i 's/\"//g' input_file
Reemplace la coma con una nueva línea
sed -i 's/\,/\n/g' input_file
Eliminar espacios en blanco
sed -i 's/\s//g input_file
Respuesta1
Para poner varios sed
comandos en un solo "guion", puede utilizar varios -e
indicadores (que son portátiles):
sed -i -e 's/\"//g' -e 's/\,/\n/g' -e 's/\s//g' input_file
O el delimitador de punto y coma (que no está disponible en todas las implementaciones):
sed -i 's/\"//g;s/\,/\n/g;s/\s//g' input_file
También necesitarás agregar manejo para los tirantes {}
-...
Dicho esto, para analizar y manejar JSON correctamente, no deberías usar sed
... tal vez intentesjq
!
jq -r 'keys[] as $k | "\($k):\(.[$k])"' input_file
Producción:
user.name1:hashed_password
user.name2:hashed_password
keys[] as $k
iterará a través de cada clave almacenando su valor en$k
- es decir:
user.name1
,user.name2
- es decir:
"\($k):\(.[$k])"
formará una cadena, sustituyendo en$k
y.[$k]
- El uso
-r
elimina las comillas de las cadenas de salida (crudomodo)
Usar sed
para procesar JSON lo abrirá a todo tipo de problemas... por ejemplo, ¿cómo manejaría la siguiente entrada (JSON completamente válida)?
{
"user.name1" :
"hashed_password",
"user.name2" :
"hashed_password"
}
Respuesta2
Cuando se trata de entradas estandarizadas como JSON, generalmente es mejor usar un analizador adecuado en lugar de expresiones regulares. Por ejemplo, convertirá correctamente cualquier secuencia de escape (¡aunque eso puede no ser posible con sus datos de entrada particulares!).
Desafortunadamente, no existen excelentes herramientas para manejar JSON dentro de coreutils.Attie siempre jq
como una opción decente si eres libre de instalar paquetes.
Si no puede instalar paquetes adicionales, no es particularmente difícil en Python. Tome este script por ejemplo:
import json,sys
for (k, v) in json.load(sys.stdin):
print(k + ":" + v)
Que se puede comprimir en una línea:
cat inputdata | python -c 'import json,sys;print("\n".join((k + ":" + v) for (k, v) in json.load(sys.stdin).items()))'
Respuesta3
Para la eliminación simple de caracteres que está realizando en estos sed
comandos, le recomendaría que utilice tr
, cuyo único propósito es eliminar, comprimir o reemplazar caracteres individuales, incluidas las nuevas líneas ( sed
se basa en expresiones regulares, que normalmente dependen de las nuevas líneas como separadores de búfer). por lo que usar sed para modificar nuevas líneas es complicado). Creo que este tr
comando hace todo lo que buscas:
cat json_filename | tr -d "{}\" \012\011\015" | tr "," "\012"
El primer tr
comando elimina todas las llaves, comillas dobles, espacios, retornos de carro (octal 012, ascii 10), tabulaciones (octal 011, ascii 9 y salto de línea (octal 015, ascii 13). El segundo tr
comando reemplaza todas las comas con retornos de carro. Siempre que los nombres y valores de las variables de su archivo JSON no contengan comas, estos comandos le permitirán evitar la necesidad de un analizador JSON dedicado.
Dicho esto, si tiene un conjunto de sed
comandos y cada uno de ellos funciona de forma independiente, combinarlos se puede lograr más fácilmente usando la sed
opción "-f" para leer los comandos separados de un archivo. Simplemente coloque las cadenas s/.../.../g en un archivo, cada cadena en su propia línea, luego especifique ese nombre de archivo después de la opción "-f". Por ejemplo, si los tres sed
comandos que enumeró son satisfactorios, puede colocarlos en un archivo llamado "json.convert.sed" que simplemente contenga esto:
s/\"//g
s/\,/\n/g
s/\s//g
Luego invocarías sed
con este archivo de comando usando:
sed -f json.convert.sed
Dicho esto, estos sed
comandos no me funcionan para lograr lo que quieres, y no estoy seguro de que alguna vez puedas sed
modificar los caracteres de nueva línea. Esto se debe a que sed
se basa en el antiguo editor de líneas "ed", diseñado para editar líneas individuales a la vez (una versión compatible con "script"), por lo que cada línea de entrada se "analiza" usando nuevas líneas como delimitadores, luego la línea (sin la nueva línea) se pasa al motor de edición, se aplican los comandos de edición y luego la línea editada se genera con una nueva línea. Luego el bucle se repite. Solo he podido utilizar sed
para modificar la nueva línea cambiando primero las nuevas líneas a algún carácter distinto (que de otro modo no aparece en la entrada) usando tr
. No tiene sentido utilizar tr
esta forma si todo lo que desea hacer es eliminar nuevas líneas, ya que tr
lo hará por usted. Pero si, por ejemplo, quisieras convertir nuevas líneas en punto y coma con un espacio final, una forma de hacerlo sería:
cat input_file | tr "\012" "%" | sed "s/%/; /g"
(Las nuevas líneas se convierten a % mediante tr
, luego sed
convierte todos los % caracteres en pares de caracteres "; ").
Respuesta4
Podrías combinarlo así:
sed -i 's/\"//g;s/\,/\n/g;s/\s//g' input_file
Olvidaste agregar la eliminación de {}
. Entonces probablemente quieras:
sed -i 's/\"//g;s/\,/\n/g;s/\s//g;s/{//g;s/}//g' input_file