Eu preciso dividir a saída de ps
, que é separada por espaçamento.
#!/bin/bash
A=$(ps -r -e -o pcpu=,comm= | head -1)
B=${A[0]}
C=${A[1]}
printf '%3s %s\n' $B $(basename $C)
A saída deve ser:
42 bar
Em vez disso, recebo:
usage: basename ...
Por que isso não funciona e, o mais importante, como faço para que funcione?
Para dividir uma string no caractere de espaço, você pode usar o operador split+glob. Isso é invocado na substituição do comando ou na expansão do parâmetro, mas obviamente não ao armazenar em uma variável escalar que só pode armazenar no máximo um valor.
É uma atribuição de variável escalar. Assim, atribuiria toda a saída a
$var
, da mesma forma que${var[0]}
. Para uma atribuição de variável de matriz, é:Agora, antes de invocá-lo, como sempre, você precisa ajustá-lo:
Observe que ele se divide em sequências de espaços e os espaços à esquerda e à direita são ignorados.
Então, você não quer invocá-lo na expansão de nem
$B
, então você precisa citá-los:$C
$(basename...)
Também não se esqueça
--
de marcar o fim das opções.Como você esqueceu as aspas
$C
($C
estando vazio no seu caso, pois${A[1]}
nunca foi atribuído nenhum valor),basename
não recebeu nenhum argumento em vez de receber esse argumento vazio e reclamar sobre isso.Outros já notaram qual é o erro em seu código e sugeriram corretamente que, para seus dados de espaço reservado iniciais, uma matriz seria a melhor escolha de estrutura de dados, além de como garantir que você divida a string corretamente etc.
Agora que sabemos qual é o seu comando real que você está analisando, podemos ser um pouco mais criativos com sugestões de melhoria.
O script a seguir pegará cada uma das linhas de saída do seu
ps
comando e as lerá como dois bits delimitados por espaço. O corpo do loop produz os bits lidos de diferentes maneiras:Aqui,
comm
manterá tudo após a primeira sequência de espaços na saída deps
(os espaços iniciais, antes da primeira coluna, seriam cortados).Obviamente, você pode inserir o seu
head -n 1
como parte do pipeline inicial, se desejar.Observe que em alguns shells, incluindo
bash
, o loop está sendo executado em um subshell, portanto, quaisquer variáveis criadas lá não estarão disponíveis após o término do pipeline. Existem duas soluções para isso embash
:lastpipe
opção shell no script comshopt -s lastpipe
ouLeia os dados no loop com uma substituição de processo:
Exemplo de execução:
defina array usando (). Se você estiver usando aspas duplas, ele usará a string inteira.
Leia mais sobre a matriz
Outra abordagem usando awk: