Comando integrado Bash mapfile
Em sistemas operacionais do tipo Unix, mapfile é um comando embutido do shell Bash. Ele lê as linhas da entrada padrão em uma variável de matriz indexada.
Para obter mais informações sobre as variáveis de array do bash, consulte arrays no bash.
Sintaxe
mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback [-c quantum]] [array]
Opções
O comando mapfile embutido usa as seguintes opções:
-n contagem |
Leia um máximo de linhas de contagem. Se a contagem for zero, todas as linhas disponíveis serão copiadas. |
-O origem |
Comece a escrever linhas na matriz da matriz na origem do número de índice. O valor padrão é zero. |
-s contagem |
Descarte as primeiras linhas de contagem antes de gravar na matriz. |
-t | Se alguma linha terminar em uma nova linha, retire-a. |
-u fd |
Leia as linhas do descritor de arquivo fd em vez da entrada padrão. |
-C callback |
Executa \/avalia uma função \/expressão, retorno de chamada, toda vez que as linhas quânticas são lidas. O valor padrão de quantum é 1, a menos que especificado de outra forma com -c. |
-c quantum |
Especifique o número de linhas, quantum, após o qual o retorno de chamada de função \/expressão deve ser executado \/avaliado se especificado com -C. |
variedade | O nome da variável de array onde as linhas devem ser escritas. Se array for omitido, a variável padrão MAPFILE será o destino. |
Notas
O nome do comando readarray pode ser usado como um apelido para o nome do comando mapfile, sem diferença na operação.
Se a opção -u for especificada, mapfile lê a partir do descritor de arquivo fd em vez da entrada padrão.
Se a matriz não for especificada, a variável padrão MAPFILE será usada como a variável da matriz de destino.
O comando mapfile não é muito portátil. Ou seja, se você deseja garantir que seu script possa ser executado em uma ampla variedade de sistemas, não é recomendado usar mapfile. É fornecido principalmente como uma conveniência. A mesma funcionalidade pode ser alcançada usando um loop de leitura, embora em geral o mapfile tenha um desempenho mais rápido.
Status de saída
O comando mapfile retorna 0 para sucesso, ou 1 se algo der errado, por exemplo, uma opção inválida é fornecida ou a variável de destino é somente leitura ou não é uma matriz.
Exemplos
O comando mapfile lê a entrada linha por linha e coloca cada linha em uma variável de array. Vamos fornecer várias linhas de entrada.
Podemos usar printf para fazer isso. É uma maneira fácil de imprimir texto com novas linhas.
Em nossa string de formato printf, podemos incluir ” n” (uma barra invertida imediatamente seguida por um n minúsculo) para criar uma nova linha. (” n” é um metacaractere, uma sequência de caracteres que representa outro caractere que não pode ser digitado literalmente, como a tecla Enter. Para obter uma lista completa de metacaracteres bash, consulte aspas em bash.)
Este comando printf imprime três linhas de texto:
printf "Line 1nLine 2nLine 3n"
Line 1 Line 2 Line 3
Queremos usar mapfile para colocar cada uma dessas linhas em seu próprio elemento de um array.
Por padrão, mapfile lê a partir da entrada padrão, então você pode ficar tentado a canalizar a saída de printf para mapfile assim:
printf "Line 1nLine 2nLine 3n" | mapfile
Você esperaria que a variável de matriz padrão MAPFILE contivesse os valores dessas linhas. Mas se você verificar o valor de MAPFILE:
echo "${MAPFILE[@]}"
[a blank line]
A variável está vazia. Porque?
Cada comando em um pipeline é executado em um subshell – uma instância de bash, executado como um processo filho. Cada subshell tem seu próprio ambiente e seu próprio escopo léxico – as variáveis que compõem o ambiente de cada subshell no pipeline não são transferidas para os outros. Em outras palavras, não há efeitos colaterais ambientais compartilhados de um elemento de um pipeline para o próximo. Em nosso exemplo acima, mapfile funciona corretamente e define os valores de MAPFILE, mas quando o subshell do comando termina, a variável MAPFILE desaparece.
Você pode ver isso se ecoar o valor de MAPFILE dentro de um subshell que também contém o comando mapfile, colocando ambos entre parênteses:
printf "Line 1nLine 2nLine 3n" | ( mapfile; echo "${MAPFILE[@]}" )
Line 1 Line 2 Line 3
No comando acima, echo imprime todos os elementos da variável de matriz MAPFILE, separados por um espaço. O espaço aparece no início das linhas 2 e 3 por causa das novas linhas em nossos dados. Nossa subcamada explícita, expressa entre parênteses, preserva o valor de MAPFILE por tempo suficiente para que possamos ver os valores.
Podemos consertar as quebras de linha removendo-as com -t:
printf "Line 1nLine 2nLine 3n" | ( mapfile -t; echo "${MAPFILE[@]}" )
Line 1 Line 2 Line 3
(Podemos colocar as quebras de linha de volta em nossa saída se usarmos printf – faremos isso nos exemplos subsequentes.)
Portanto, mapfile está funcionando, mas a variável de array está inacessível para o shell pai. Normalmente, entretanto, você desejará que a variável MAPFILE persista para os comandos subsequentes. Você pode fazer isso com a substituição do processo.
Usando mapfile com substituição de processo
Com a substituição do processo, podemos redirecionar a saída para mapfile sem usar um pipeline.
mapfile -t < <(printf "Line 1nLine 2nLine 3")
Vejamos as partes individuais deste comando:
mapfile -t | Mapfile obtém a entrada da entrada padrão e retira as novas linhas (-t) do final de cada linha. Isto é (normalmente) o que você deseja: apenas o texto da linha é armazenado em seu elemento de array, e o caractere de nova linha é descartado. |
< | O primeiro <é um caractere de redirecionamento. Ele espera ser seguido por um nome de arquivo ou descritor de arquivo. O conteúdo desse arquivo é redirecionado para a entrada padrão do comando anterior. |
<(...) |
Esses caracteres indicam substituição de processo, que retorna um descritor de arquivo. Os comandos entre parênteses são executados e sua saída é atribuída a este descritor de arquivo. Em qualquer comando bash, você pode usar a substituição de processo como um nome de arquivo. |
Quando você executa o comando inteiro, mapfile lê silenciosamente nossas três linhas de texto e coloca cada linha em elementos individuais da variável de array padrão, MAPFILE.
Podemos verificar isso usando printf para imprimir os elementos do array.
printf "%s" "${MAPFILE[@]}"
O primeiro argumento, “% s”, é a string de formato printf. O segundo argumento, “${MAPFILE[@]} “, é expandido por bash. Todos os elementos (” @ “) da matriz MAPFILE são expandidos para argumentos individuais. (Para obter mais informações, consulte: Referência a elementos da matriz em bash.)
Line 1Line 2Line 3
Como você pode ver, nossas três linhas de texto são impressas lado a lado. Isso porque eliminamos as novas linhas com -t e printf não produz novas linhas por padrão.
Para especificar que printf imprima uma nova linha após cada linha, use n na string de formato:
printf "%sn" "${MAPFILE[@]}"
Line 1 Line 2 Line 3
Para acessar elementos individuais da matriz, substitua @ por um número de índice. A numeração é baseada em zero, então 0 indexa o primeiro elemento, 1 indexa o segundo, etc:
printf "%sn" "${MAPFILE[0]}"
Line 1
printf "%sn" "${MAPFILE[2]}"
Line 3
Comandos relacionados
read – Leia uma linha, divida-a em palavras e atribua cada palavra a uma variável.
0 Comments