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 tr
para 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.
ambiguous redirect
é porqueseu código não tem aspas duplas.- 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<<<
. function
é uma palavra reservada. Existe uma maneira de nomear uma função,function
mas seu uso posterior é inconveniente.- (terminologia em seu comentário) Função não é filho.
- Chama-se uma função pelo seu nome, não com
bash -c
.Minha resposta para sua outra perguntase aplica. - 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 demapfile
. Invoquehelp mapfile
para aprender.- Outros materiais de pesquisa:
<<<
,<( … )
,matrizes. - Não há como inserir
export
uma variável de array no ambiente. Poderíamos dizer
readarray
para 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 linhastr
ereadarray
uso 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
sed
em vez detr
para transformar substrings de delimitadores com espaços adjacentes em caracteres de nova linha únicos. Areadarray …
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 usamosread
, a nova linha final (que aparece devido ao modo como certos redirecionamentos e ferramentas funcionam) não é apenas inofensiva, é necessária. - Eu adicionei a
extra
variável. Se houver mais campos do que o esperado, os campos excessivos ocuparãoextra
. Semextra
eles afetariam$wtf3
. - Você pode
export
essas variáveis.
- Aqui usamos explicitamente
Se você for manipular arquivos/fluxos contendo (muitos) registros em uma forma
foo|bar|baz|…
(oufoo | bar | baz | …
similar), familiarize-se com oawk
.