¿Cómo podemos separar subcadenas usando un delimitador en Linux?

¿Cómo podemos separar subcadenas usando un delimitador en Linux?

Tengo la cadena a continuación:

/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand

Soy principiante en Linux. ¿Cómo puedo separar usando "|"? como delimitador y asignar en una variable? Estoy pasando la cadena completa como parámetro y necesito dividir/cortar los campos por separado.

Por ejemplo:

function()
{
while read -r record; do
## here i need the fields to cut the fields and assign to a variable #####
done < $0 
}

bash -c function "/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand"

Cuando probé el ejemplo anterior arroja un error $0: ambiguous redirect.

Respuesta1

Puedes usar trpara separar usando delimitador.

En el siguiente ejemplo reemplazamos |pornewline

variable=$(echo "/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand" | tr "|" "\n")

echo $variable

También puedes usar

echo yourtext | tr -d "|"

Vercomando tr

Respuesta2

Hay tantas cuestiones además de la principal.

  1. ambiguous redirectes porquetu código carece de comillas dobles.
  2. La redirección <toma datos de un archivo. Su cadena no apunta a un archivo (ruta). En Bash puedes tomar datos de una cadena con <<<.
  3. functiones una palabra reservada. Hay una manera de nombrar una función function, pero su uso posterior es inconveniente.
  4. (terminología en su comentario) La función no es un niño.
  5. Se llama a una función por su nombre, no por bash -c.Mi respuesta a tu otra pregunta.aplica.
  6. Entonces al primer argumento se le llama $1, no $0.

Este código funciona, aunque no estoy seguro de que sea exactamente lo que quieres:

#!/bin/bash

split_string ()
{
   readarray -t arrayv < <(tr '|' '\n' <<< "$1")
}

split_string '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand'

# now arrayv is an array variable (indexed from 0)
# retrieving few values
echo "${arrayv[0]}"
echo "${arrayv[5]}"
echo "${arrayv[9]}"

Notas:

  • Usted citó dos veces la cadena. Recuerde que una cadena entre comillas dobles sufre ciertas expansiones. Su cadena no contiene nada que pueda expandirse (por ejemplo $), por lo que las comillas dobles están bien en este caso particular. En general, utilice comillas simples para suprimir las expansiones.
  • readarrayes sinónimo de mapfile. Invocar help mapfilepara aprender.
  • Otros forrajes de investigación:<<<,<( … ),matrices.
  • No hay forma de introducir exportuna variable de matriz en el entorno.
  • Podríamos decir readarrayque se use |como delimitador:

     readarray -t -d '|' arrayv <<< "$1"
    

    pero luego el último "campo" incluiría un carácter de nueva línea al final (aparecería debido a cómo <<<funciona). Convierto todos los delimitadores en nuevas líneas try luego readarrayuso su configuración predeterminada (nuevas líneas como delimitadores).

  • Los espacios no pertenecen a delimitadores, se convierten en parte de los valores almacenados. Úselo seden lugar de trpara convertir subcadenas de delimitadores con espacios adyacentes en caracteres de nueva línea única. La readarray …línea será:

    readarray -t arrayv < <(sed 's/ *| */\n/g' <<< "$1")
    
  • Si va a utilizar la función sólo una vez, no necesita ninguna función. Esta línea (fuera de cualquier función) hará el trabajo:

    readarray -t arrayv < <(tr '|' '\n' <<< '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand')
    

    Definí una función (y luego la usé solo una vez) porque intentaste definir una.

  • Si su cadena de entrada consta de un número fijo de campos y los campos tienen significado, puede ser bueno asignarlos a diferentes variables (regulares, no de matriz) cuyos nombres tengan significado. Ejemplo:

    IFS='|' read -r path1 path2 path3 path4 path5 ip path6 wtf1 wtf2 wtf3 extra < <(sed 's/ *| */|/g' <<< '/a585/app/data/CCN_text/CCN_split_files/ccn.email.list.file07 | /svr00c8/n585 | /a585/app/data/CCN_text | /a585/app/data/CCN_text | /a585/app/data/muttrc | 153.2.254.229 | /a001/odbi_land/ondemand/download/scriptload | DVLP | cmodappl | ondemand')
    echo "$ip"
    echo "$wtf3"
    

    Notas específicas:

    • Aquí usamos explícitamente |como delimitador. Cuando usamos read, la nueva línea final (que aparece debido a cómo funcionan ciertas redirecciones y herramientas) no solo es inofensiva, sino que es obligatoria.
    • Agregué la extravariable. Si hay más campos de los esperados, se ocuparán los campos excesivos extra. Sin extraellos afectarían $wtf3.
    • Puedes exportestas variables.
  • Si va a manipular archivos/transmisiones que contienen (muchos) registros en una forma foo|bar|baz|…(o foo | bar | baz | …similar), familiarícese con awk.

información relacionada