대다수의 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
'linux' 카테고리의 다른 글
[linux] vi로 파일을 열었는데 @@@@@@만 뜨는 문제 (0) | 2022.02.21 |
---|---|
[shell script] getopts - 스크립트 옵션 처리 (0) | 2021.12.03 |
Vundle 사용 과정 요약 (0) | 2021.11.27 |
vi와 vim (Vundle 사용 관련) (0) | 2021.11.27 |