Como podemos separar a substring usando o delimitador no Linux?

Como podemos separar a substring usando o delimitador no Linux?

Eu tenho a string abaixo:

/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

Sou iniciante em Linux. Como posso separar usando "|" como delimitador e atribuir em uma variável? Estou passando a string inteira como parâmetro e preciso dividir\cortar os campos separadamente.

Por exemplo:

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"

Quando tentei o exemplo acima, ocorreu um erro $0: ambiguous redirect.

Responder1

Você pode usar trpara separar usando delimitador

No exemplo a seguir substituímos |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

Você também pode usar

echo yourtext | tr -d "|"

Vercomando tr

Responder2

Tantas questões além da principal.

  1. ambiguous redirecté porqueseu código não tem aspas duplas.
  2. O redirecionamento <coleta dados de um arquivo. Sua string não aponta para um arquivo (caminho). No Bash você pode obter dados de uma string com <<<.
  3. functioné uma palavra reservada. Existe uma maneira de nomear uma função, functionmas seu uso posterior é inconveniente.
  4. (terminologia em seu comentário) Função não é filho.
  5. Chama-se uma função pelo seu nome, não com bash -c.Minha resposta para sua outra perguntase aplica.
  6. Então o primeiro argumento é referido como $1, não $0.

Este código funciona, embora não tenha certeza se é exatamente o que você deseja:

#!/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:

  • Você colocou aspas duplas na string. Lembre-se de que uma string entre aspas duplas sofre certas expansões. Sua string não contém nada que possa ser expandido (por exemplo, $), portanto, aspas duplas são aceitáveis ​​neste caso específico. Em geral, use aspas simples para suprimir expansões.
  • readarrayé sinônimo de mapfile. Invoque help mapfilepara aprender.
  • Outros materiais de pesquisa:<<<,<( … ),matrizes.
  • Não há como inserir exportuma variável de array no ambiente.
  • Poderíamos dizer readarraypara usar |como delimitador:

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

    mas o último "campo" incluiria um caractere de nova linha à direita (apareceria devido ao <<<funcionamento). Eu transformo todos os delimitadores em novas linhas tre readarrayuso sua configuração padrão (novas linhas como delimitadores).

  • Os espaços não pertencem aos delimitadores, eles passam a fazer parte dos valores armazenados. Use sedem vez de trpara transformar substrings de delimitadores com espaços adjacentes em caracteres de nova linha únicos. A readarray …linha será:

    readarray -t arrayv < <(sed 's/ *| */\n/g' <<< "$1")
    
  • Se você for usar a função apenas uma vez, não precisará de nenhuma função. Esta linha (fora de qualquer função) fará o trabalho:

    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')
    

    Eu defini uma função (e usei-a apenas uma vez) porque você tentou definir uma.

  • Se sua string de entrada consistir em um número fixo de campos e os campos tiverem significado, pode ser bom atribuí-los a diferentes variáveis ​​(não-array, regulares) cujos nomes tenham significado. Exemplo:

    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:

    • Aqui usamos explicitamente |como delimitador. Quando usamos read, a nova linha final (que aparece devido ao modo como certos redirecionamentos e ferramentas funcionam) não é apenas inofensiva, é necessária.
    • Eu adicionei a extravariável. Se houver mais campos do que o esperado, os campos excessivos ocuparão extra. Sem extraeles afetariam $wtf3.
    • Você pode exportessas variáveis.
  • Se você for manipular arquivos/fluxos contendo (muitos) registros em uma forma foo|bar|baz|…(ou foo | bar | baz | …similar), familiarize-se com o awk.

informação relacionada