리눅스 bash 스크립트에서 텍스트 파일을 읽어서 각 행을 배열(array)에 할당하는 방법이다. 예를 들어 test.txt 파일의 내용이 아래와 같다고 생각해 보자.
# test.txt 파일 내용 확인
cat test.txt
my name is john
your name is jane
his name is thomas
위의 내용을 배열 arr에 할당하는 작업이다. arr[0]의 내용은 "my name is john", arr[1]의 내용은 "your name is jame" 이런 식이 될 것이다. 배열에 대한 자세한 내용은 이전 게시물을 참고하자. 여기로
cat 명령을 이용해서 파일 내용을 출력하고 이것을 그대로 배열 변수에 할당할 경우, 한 줄씩 할당되는 것이 아니라 한 단어씩 할당된다. 아래의 예시를 보자.
# test.txt의 내용을 배열 arr에 할당
arr=(`cat test.txt`)
# 배열 원소 확인
echo ${arr[0]}
my
echo ${arr[1]}
name
echo ${arr[2]}
is
이렇게 되는 이유는 bash의 내부 필드 구분자(internal field separator)가 공백/탭/줄바꿈이기 때문이다. 따라서 한줄을 배열 원소 하나에 대응시키려면 구분자를 줄바꿈(newline) 하나로 제한시켜야 한다. 구분자는 변수 IFS에 설정되어 있다.
기존의 IFS 값을 IFS_backup 변수에 저장한 후, 배열 할당 작업을 하고 나서 원상복구하는 방식으로 작업을 하면 된다.
# 기존 IFS 백업
IFS_backup="$IFS"
# IFS 값을 줄바꿈으로 변경
IFS=$'\n'
# 배열 할당
arr=(`cat test.txt`)
# IFS 원상복구
IFS="$IFS_backup"
이제 배열 원소의 내용을 확인해 보면 하나의 원소에 파일 내용이 한 줄씩 들어가 있는 것을 볼 수 있다.
# 배열 원소 확인
echo ${arr[0]}
my name is john
echo ${arr[1]}
your name is jane
위의 예시에서 IFS 변수의 내용을 줄바꿈으로 설정할 때 echo 명령을 이용하면 제대로 되지 않음에 유의하자.
# IFS를 줄바꿈으로 설정 시도. 이런 식으로는 작동하지 않음
IFS=`echo -e "\n"`
제대로 작동하지 않는 이유는, 역따옴표(`) 안에 제시한 명령을 실행한 결과를 IFS에 할당하면서 맨 뒤에 있는 줄바꿈을 자동으로 제거하기 때문이다. 따라서 반드시 $'\n' 형태를 사용해야 한다.
# IFS를 줄바꿈으로 설정
IFS=$'\n'
# test.txt 파일 내용 확인
cat test.txt
my name is john
your name is jane
his name is thomas
위의 내용을 배열 arr에 할당하는 작업이다. arr[0]의 내용은 "my name is john", arr[1]의 내용은 "your name is jame" 이런 식이 될 것이다. 배열에 대한 자세한 내용은 이전 게시물을 참고하자. 여기로
cat 명령을 이용해서 파일 내용을 출력하고 이것을 그대로 배열 변수에 할당할 경우, 한 줄씩 할당되는 것이 아니라 한 단어씩 할당된다. 아래의 예시를 보자.
# test.txt의 내용을 배열 arr에 할당
arr=(`cat test.txt`)
# 배열 원소 확인
echo ${arr[0]}
my
echo ${arr[1]}
name
echo ${arr[2]}
is
이렇게 되는 이유는 bash의 내부 필드 구분자(internal field separator)가 공백/탭/줄바꿈이기 때문이다. 따라서 한줄을 배열 원소 하나에 대응시키려면 구분자를 줄바꿈(newline) 하나로 제한시켜야 한다. 구분자는 변수 IFS에 설정되어 있다.
기존의 IFS 값을 IFS_backup 변수에 저장한 후, 배열 할당 작업을 하고 나서 원상복구하는 방식으로 작업을 하면 된다.
# 기존 IFS 백업
IFS_backup="$IFS"
# IFS 값을 줄바꿈으로 변경
IFS=$'\n'
# 배열 할당
arr=(`cat test.txt`)
# IFS 원상복구
IFS="$IFS_backup"
이제 배열 원소의 내용을 확인해 보면 하나의 원소에 파일 내용이 한 줄씩 들어가 있는 것을 볼 수 있다.
# 배열 원소 확인
echo ${arr[0]}
my name is john
echo ${arr[1]}
your name is jane
위의 예시에서 IFS 변수의 내용을 줄바꿈으로 설정할 때 echo 명령을 이용하면 제대로 되지 않음에 유의하자.
# IFS를 줄바꿈으로 설정 시도. 이런 식으로는 작동하지 않음
IFS=`echo -e "\n"`
제대로 작동하지 않는 이유는, 역따옴표(`) 안에 제시한 명령을 실행한 결과를 IFS에 할당하면서 맨 뒤에 있는 줄바꿈을 자동으로 제거하기 때문이다. 따라서 반드시 $'\n' 형태를 사용해야 한다.
# IFS를 줄바꿈으로 설정
IFS=$'\n'
덧글
몇일동안 고민을 해봐도 잘 해결이 되지 않는 부분이 있어서 그런데 혹 도움을 얻을수 있을까요?
아래처럼 2개의 텍스트 파일이 있는데 텍스트1 파일의 특정 부분에 텍스트2 파일의 각행의 문자열로 대치하고 싶습니다.
# 텍스트1 파일 내용 확인
가나다라 12.345 67.890 <---- 숫자 부분을 텍스트2 파일의 1,2필드에서 가져오고 싶습니다.
마바사아 a bc <------ 알바펫 부분을 텍스트2 파일의 3,4필드에서 가져오고 싶습니다.
# 텍스트2 파일 내용 확인
42.546 74.345 d ef
위와 같은 상황입니다.
우선 텍스트1 파일에 텍스트2 파일의 내용을 다 합친 test3 파일을 새로 만든 후, test3 파일을 한 행씩 읽어서 처리하면 되지 않을까 싶습니다. 2개 파일의 내용을 하나로 모으는 방법은 이전 게시물을 참고하시기 바랍니다. awk를 이용한 방법입니다.
[bash: awk] 2개의 파일에 있는 자료 종합하기
http://bahndal.egloos.com/598483
그걸 모두 텍스트 1 형식에 대입하고 싶습니다.
# 텍스트2 파일 내용 확인
42.546 74.345 d ef
65.456 36.346 g dy
32.346 72.673 h os
94.366 34.389 b.cx
.
.
.
제가 질문을 어렵게해서 원하던 답변은 아니었지만 조금더 고민을 해봐야 할것 같네요 ^^
예시를 한글,알파벳으로 구분을 해놓기 보다 원하는곳을 구분하기 위해 숫자,알파벳으로 질문을 드렸네요.
텍스트1 내용의 바꾸고 싶은 부분에 텍스트2의 각행의 특정 부분을 대치하는 개념입니다.
결과물-------------
사자하타
가나다라 [텍스트2 파일 1행의 1,2필드 대치]
마바사아 [텍스트2 파일 1행의 3,4필드 대치]
하나호다
사자하타
가나다라 [텍스트2 파일 2행의 1,2필드 대치]
마바사아 [텍스트2 파일 2행의 3,4필드 대치]
하나호다
사자하타
가나다라 [텍스트2 파일 3행의 1,2필드 대치]
마바사아 [텍스트2 파일 3행의 3,4필드 대치]
하나호다
이런식으로 텍스트2 파일의 행 갯수 만큼 위 형식으로 결과물이 나와야합니다.
다시한번 답변 주셔서 감사드립니다.
많이 더 고민해볼게요 ^^
awk '{ print "사자하타n가나다라t" $1 "t" $2 "n마바사아t" $3 "t" $4 "n하나호다n" }' test2.txt
말씀해주신대에서 응용하면 원하는 답을 얻을수 있을것 같습니다.
밑도 끝도 없이 답만 원하는 댓글에 친절히 답변 주셔서 감사합니다~
항상 좋은 일들만 가득하길 바랄게요~!!
arr=(`cat test.txt`)
이렇게 하니 그냥 안에 있는 문자가 그대로 할당이 되는데 파일의 내용을 배열에 할당하려면 어떻게 하나요?
http://bahndal.egloos.com/631090