본문 바로가기

linux

[bash] IFS란

대다수의 Programming Languages 에서 편하게 반복문을 제공할 수 있도록 Array 를 제공한다 

 

셸 스크립트를 짤 때에도 여러 항목에 대해 반복문을 돌릴 때가 많이 있다

예를들어 특정 디렉토리에 a, b, c, d, e 라는 5개의 파일이 존재한다고 가정하면

ls 명령어는 다음 결과를 반환한다

a b c d e

이는 단순히 "a b c d e" 라는 문자열이다

일반적인 상식으로 이 5개의 알파벳에 대해 반복문을 사용하고 싶으면 space(" ")를 기반으로 split하여 배열  만든 후 순회하며 사용하게 될 것이다.

 

하지만 셸 스크립트에서 그러한 배열화 작업 없이 간편하게 array처럼 사용할 수 있다.

가령 다음과 같은 작업이 가능하다

for f in $(ls); do readlink -f $f; done

 

이상하지 않은가?

$(ls)로 반환된 것은 "a b c d e" 라는 문자열이기 때문에 "a b c d e"라는 이름의 파일을 찾을 것 같지만,

실제로는 a, b, c, d ,e에 대해 작업을 수행한다

 

이런 작업을 가능하게 해 주는 것이 바로 IFS라는 요소 이다.

 

IFS는 Internal Field Separator의 약자이다. 직역하면 필드를 나눠준다는 의미인데

무언가에 의해 치환된 문자열을 특정 문자를 기준으로 나눠준다는 의미이다.

도대체 뭘 어떻게 나누길래 "a b c d e" 는 다섯개의 요소를 가진 유사배열이 되는 걸까?

 

 

IFS의 기본값은 ' \t\n'이다. 이 것이 의미하는 바는 다음과 같다. 

  • ' ' 는 모두가 아는 공백문자
  • '\t' 는 탭문자
  • '\n' 는 리눅스의 개행문자이다

누군가는 눈치 챘겠지만, 하나가 아닌 3개가 지정되어 있다.

예를들어 ':,^'로 설정되면, :와 ,와 ^ 세 가지 값을 가지는 것이다

 

우리가 "a b c d e" 라는 문자열을 어떠한 변수에 저장해 두고 출력하게 되면 "a b c d e" 라는 문자열로 치환된다

이 문자열은 각 알파벳 사이사이에 있는 공백문자열 ' '에 의해 a, b, c, d, e로 나누어지게 되는 것이다

또한

"a

b

c

d

e"

이 치환된 값도, 

"a   b   c   d   e" (사이의 공백은 tab이라고 가정)

도 나누어지게 된다.

치환이라는 말을 벌써 세번이나 사용했다는 것을 기억하자

 

 

아직 문자열을 나눈다는게 무슨 의미일지 모호할 수 있다

다음 실험을 보자

 

실험

#!/bin/bash
str1="a b c d e"
str2="a:b:c:d:e"

echo str1 separate Test
for tmp in $str1; do
    echo $tmp
done

echo str2 separate Test
for tmp in $str2; do
    echo $tmp
done

간단한 스크립트를 하나 구성해 보았다

1번 문자열의 알파벳은 공백문자 ' ' 에 의해 분할되어 있고

2번 문자열의 알파벳은 ':' 에 의해 분할되어 있다.

 

여기서 주목할 점은 단순 문자열에 반복문을 적용했다는 점이다.

해당 소스의 실행 출력문을 보자

str1 separate Test
a
b
c
d
e
str2 separate Test
a:b:c:d:e

1번 문자열은 공백을 기준으로 나누어져 마치 배열과 같이 한글자씩 차례로 반복이 실행되었다.

 

 

그럼 이제 IFS 값을 변경하는 로직을 섞어 보자 

#두번째 실행
echo change IFS
old_ifs=$IFS
IFS=":;^"


echo str1 separate Test
for tmp in $str1; do
    echo $tmp
done

echo str2 separate Test
for tmp in $str2; do
    echo $tmp
done

IFS=$old_ifs

일반적으로 IFS를 변경할 때는 위의 old_ifs 와 같은 임시변수에 저장해두는 식으로 사용한다

자, 이제 IFS가 다른 값으로 변경 되었다.

위와 같은 코드를 실행했을 때 결과 값이 달라질까?

str1 separate Test
a b c d e
str2 separate Test
a
b
c
d
e

바뀐 IFS에 속하는 : 문자에 의해 2번 문자열이 분할되었다!

 

이 기능은 아주 많은 경우에 유용하게 사용될 것이다

예를들어 다음과 같이 띄어쓰기가 포함된 여러 파일 목록에 대해 유용하게 사용될 것이다

$ ls
'test file 1'  'test file 2'  'test file 3'  'test file 4'  'test file 5'

 

 

 

레퍼런스가 정말 적었기 때문에 틀린 내용이 있을 수도 있다

 

 

유용한 링크

https://mywiki.wooledge.org/IFS