Capture en las variables del shell los arguments después de un command (entre paréntesis)

Supongamos que tengo un file que contiene, entre muchas otras cosas,

\ command {arg1, arg2, arg3}

(los arguments han sido paths, expresados ​​con / , . , caracteres y numbers)

Pero que un usuario también puede llamarlo con

 \command{arg1, arg2 , arg3 } 

Es decir, en varias líneas y con espacios superfluos.

Me gustaría encontrar un patrón regular para include en un script de shell para que n variables contengan los n arguments. Cómo proceder ?


Me las arreglé para escribir

 echo "\command{arg1, arg2 , arg3 }" | sed -n -e 's/\\command//p' | sed 's/,/\n/' | sed 's/{\|}//' 

pero eso solo genera arg1 , y ni siquiera estoy seguro de cómo almacenarlo en una variable.

Relacionado:

  • hacer coincidir el text entre paréntesis en un text de líneas múltiples
  • Encontrar cadenas entre dos personajes
  • sacando solo la parte que coincide con la expresión regular
  • cómo eliminar todo entre un grupo de corchetes

Pero no pude combinar todos esos ingnetworkingientes para get lo que quiero.

Me gustaría encontrar un patrón regular para include en un script de shell para que n variables contengan los n arguments

A continuación, crea un arglist matriz de arglist que contiene cada uno de los arguments:

 $ readarray -t arglist < <(echo "\command{arg1, arg2 , arg3 }" | sed -n '/\\command/{ :a;/}/!{N;ba}; s/\\command{//; s/[ \n}]//g; s/,/\n/g; p}') 

Al usar la statement declare , podemos ver que funcionó:

 $ declare -p arglist declare -a arglist='([0]="arg1" [1]="arg2" [2]="arg3")' 

Aquí hay otro ejemplo con los arguments en una línea:

 $ readarray -t arglist < <(echo "\command{arg1, arg2, arg3, arg4}" | sed -n '/\\command/{ :a;/}/!{N;ba}; s/\\command{//; s/[ \n}]//g; s/,/\n/g; p}') 

Nuevamente, funciona:

 $ declare -p arglist declare -a arglist='([0]="arg1" [1]="arg2" [2]="arg3" [3]="arg4")' 

Tenga en count que el espacio en < <( es esencial. Estamos networkingirigiendo la input de una sustitución de process. Sin el espacio, bash intentará algo completamente distinto.

Cómo funciona

El command sed es un poco sutil. Veámoslo una pieza a la vez:

  • -n

    No imprima líneas a less que se le pregunte explícitamente.

  • /\\command/{...}

    Si encontramos una línea que contiene \command , entonces ejecutamos los commands encontrados en los corchetes que son los siguientes:

  • :a;/}/!{N;ba}

    Esto lee las líneas en el buffer del patrón hasta que encontremos una línea que contenga } . De esta manera, recibimos todo el command de una vez.

  • s/\\command{//

    Eliminar el \command{ string.

  • s/[ \n}]//g

    Elimine todos los espacios, llaves de cierre y saltos de línea.

  • s/,/\n/g

    Reemplazar comas con nuevas líneas. Cuando se hace esto, cada argumento está en una línea separada, que es lo que readarray quiere.

  • p

    Impresión.

Con perl :

 perl -l -0777 -ne ' $n = 0; for (/\\command\{\s*(.*?)\s*\}/sg) { $n++; $i = 0; for $arg (split /\s*,\s*/, $_) { $arg =~ s/'\''/$&\\$&$&/g; print "arg${n}[$i]='\''$arg'\''"; $i++; } } print "n=$n"' the-file 

Produciría algo como:

 arg1[0]='arg1' arg1[1]='arg2' arg1[2]='arg3' n=1 

Que podrías evaluar como:

 eval "$(perl ...)" 

para crear arrays $arg1 , $arg2 … para cada uno de los \command s.