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.


Quase tudo que você precisa saber sobre a variável IFS

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'	# Usando s 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

Adicionar comentário

* Campos obrigatórios
5000
Powered by Commentics

Comentários

Nenhum comentário ainda. Seja o primeiro!


Veja a relação completa dos artigos de Julio Cezar Neves