De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.
Colaboração: Julio Cezar Neves
Data de Publicação: 29 de setembro de 2023
Existe uma variável intrínseca ao sistema chamada de IFS (Inter Field Separator – Separador entre os campos) que, como o nome diz, trata-se do separador padrão (default) entre dois campos para diversos comandos e nesse artigo estudaremos seu comportamento em alguns deles.
Assume-se que seu valor seja espaço, uma vez que é assim que ele se apresenta. Mas vejamos:
$ echo $IFS # Nada aparece quando listamos a variável
$ hexdump -Cc <<< "$IFS" # Lista os valores em hexadecimal e os interpreta
00000000 20 09 0a 0a | ...|
0000000 \t \n \n
No entanto, quando passamos o seu conteúdo para o comando hexdump
(octal dump) com as opções para listar e interpretar o seu conteúdo
vemos que é composto por três bytes que significam:
20 | Espaço |
09 | <TAB> |
0a | Line feed |
Explicando melhor o que quis dizer no início desse artigo, é que uma grande característica desta variável é que sempre que o Shell consegue vê-la, exibe-a como um espaço em branco, repare:
$ printf -v Nums "1\tUm\n2\tDois\n3 Três"
$ echo $Nums
1 Um 2 Dois 3 Três
Apesar do printf
ter gerado a variável (-v
) Nums
com <TAB>s
(\t
), <ENTER>
s (\n
) e espaços, quando listamos a variável sem
protegê-la da interpretação do Shell, cada um desse conjunto de caracteres
era exibido somente como um espaço em branco e por isso, muitas vezes é
conveniente protegê-la de forma que o Shell fique na dele e não faça
isso. Olha só:
$ echo "$Nums" Aspas protegndo da interpretação
1 Um O Shell viu a e o
2 Dois Idem
3 Três Não transformou todos em um único espaço
Por outro lado, não proteger por vezes ajuda:
$ Reg=$(grep ^root: /etc/passwd) $ echo "$Reg" root:x:0:0:super usuário do sistema:/root:/bin/bash $ echo $Reg root x 0 0 super usuário do sistema /root /bin/bash
Se os dois pontos (:
) se transformaram em espaços, posso decompor seus
campos de algumas formas. Veja:
$ for Pedaco in $Reg; { echo $((++Cont)) -- $Pedaco; }
1 -- root
2 -- x
3 -- 0
4 -- 0
5 -- super usuário do sistema
6 -- /root
7 -- /bin/bash
Como o for
trata individualmente os campos de uma lista, basta deixar o
Shell "ver" o conteúdo do registro, para que ele mesmo o transforme numa
lista. Então só foi necessário cada um dos campos lidos, mas acrescentei
um contador para poder mostrar pela linha número 5, que os espaços originais
foram preservados.
Se eu quisesse transformar cada um desses campos num parâmetro posicional bastaria fazer:
$ set $Reg # Na atribuição os parâmetros devem
# ser separados por espaços
$ echo $1 -- $5 -- $7
root -- super usuário do sistema -- /bin/bash
Uma manipulação muito interessante desta variável é feita pelo comando read que também a usa como separador, mas para mostrar isso, primeiramente vamos devolver-lhe seu valor padrão:
$ IFS=$' \n\t' # Sintaxe permitida só no Bash
$ read Var1 Var2 Var3 <<< "111 222 333"
$ echo $Var1 -- $Var2 -- $Var3
111 –- 222 – 333
Como você viu cada campo separado pelo IFS
foi para uma variável diferente,
o que nos permite ler diversos campos de uma só vez. Mas será que isso
serve para qualquer caractere do $IFS
? Vamos criar uma lista separada por
<TAB>
s para testar:
$ ParaLer=$'111\t222\t333\t444' # Usandos como separadores $ echo "$ParaLer" 111 222 333 444 $ read Var1 Var2 Var3 <<< "$ParaLer" $ echo $Var1 -- $Var2 -- $Var3 111 -- 222 –- 333 444
Como você pode ver, cada variável recebeu um valor, mas como tínhamos 4 campos e somente 3 variáveis, a última recebeu todo o resto.
Vamos agora entender a manipulação importante que mencionei. Agora os campos estarão separados por diversos caracteres, veja:
$ read Var1 Var2 Var3 <<< "111-222:333"
$ echo $Var1 -- $Var2 -- $Var3
111-222:333 -- --
Assim deu zebra porque nenhum deles é um delimitador válido, mas é permitido fazer o seguinte:
$ IFS=:- read Var1 Var2 Var3 <<< "111-222:333"
$ echo $Var1 -- $Var2 -- $Var3
111 -- 222 –- 333
Repare que entre a atribuição do IFS
e o comando read
, temos somente um
espaço em branco, isso significa que esse IFS
é válido somente enquanto
a instrução está sendo executada, é uma parceria que essa variável e
o comando mantêm entre si. Apesar de haver trocado seu conteúdo durante
o read
, após a execução seu valor anterior foi restaurado:
$ hexdump -Cc <<< "$IFS" # Lista os valores em
# hexadecimal e os interpreta
00000000 20 09 0a 0a | ...|
0000000 \t \n \n
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Comentários