줄 종결자가 이 Bash 스크립트의 출력을 변경하는 이유는 무엇입니까?

줄 종결자가 이 Bash 스크립트의 출력을 변경하는 이유는 무엇입니까?

스크립트를 디버깅하는 동안 마침내 원인을 찾았지만 이유를 이해할 수 없습니다.

탭으로 구분된 텍스트 파일의 예에는 다음이 포함됩니다.

$ cat list1.txt
123 Fake St Miami   FL
456 None Rd San Francisco CA
789 Nowhere Dr  Denver  CO

원래 vi를 사용하여 생성되었으며 파일은 이를 다음과 같이 식별합니다.

$ file list1.txt
list1.txt: ASCII text

이 줄을 실행하면(편집: 가독성을 높이기 위해 게시물을 여러 줄로 변경) 각 줄을 3개의 변수로 읽어 스크립트에 지정된 순서대로 인쇄합니다. 디버깅할 때 순서를 매우 명확하게 설명하려고 하므로 문자열 연결은 매우 복잡합니다.

$ while IFS="     " read -r addr1 city state
do
  data0="'"
  data1='companyName=&'
  data2="address1=$addr1"
  data3='&city='
  data4="$city"
  data5='&state='
  data6="$state"
  data7='&urbanCode=&zip='
  data8="'"
  data=${data0}${data1}${data2}${data3}${data4}${data5}${data6}${data7}${data8}
  echo "$data"
done < list1.txt

'companyName=&address1=123&city=Fake&state=St   Miami   FL&urbanCode=&zip='
'companyName=&address1=456&city=None&state=Rd   San Francisco CA&urbanCode=&zip='
'companyName=&address1=789&city=Nowhere&state=Dr    Denver  CO&urbanCode=&zip='

파일 list1.txt DOS 형식을 변경하면 출력 순서가 변경됩니다.

$ unix2dos list1.txt
unix2dos: converting file list1.txt to DOS format...
$ file list1.txt
list1.txt: ASCII text, with CRLF line terminators
$ while IFS="     " read -r addr1 city state; do  data0="'";  data1='companyName=&';  data2="address1=$addr1";  data3='&city=';  data4="$city";  data5='&state=';  data6="$state";  data7='&urbanCode=&zip=';  data8="'";  data=${data0}${data1}${data2}${data3}${data4}${data5}${data6}${data7}${data8};  echo "$data"; done < list1.txt
&urbanCode=&zip='ress1=123&city=Fake&state=St   Miami   FL
&urbanCode=&zip='ress1=456&city=None&state=Rd   San Francisco CA
&urbanCode=&zip='ress1=789&city=Nowhere&state=Dr    Denver  CO

왜 이런 일이 발생합니까? GNU 배쉬, 버전 3.2.57

답변1

DOS 형식의 텍스트 파일에서 세 개의 변수로 한 줄을 읽을 때 마지막 변수는 state캐리지 리턴 문자로 끝납니다. 이는 DOS 텍스트 파일이 "줄 바꿈"을 나타내기 위해 문자 시퀀스 CR+LF(캐리지 리턴 다음에 줄 바꿈)를 사용하기 때문입니다. Unix 텍스트 파일은 줄바꿈에 줄 바꿈만 사용하고, DOS 텍스트 파일의 캐리지 리턴은 줄 끝의 다른 문자로 처리됩니다.

터미널로 출력할 때 $state이 캐리지 리턴은 출력이 줄의 시작 부분으로 점프하도록 합니다(캐리지 리턴 문자의 목적은 라인 프린터의 캐리지 리턴이었던 "캐리지 리턴"을 반환하는 것입니다). 줄의 시작 부분) 다음 문자열은 줄의 맨 처음 부분에 배치되어 이전에 터미널에서 이 위치에 출력된 모든 텍스트를 덮어씁니다.

그래서 첫 번째 줄을 얻게 될 것입니다.

'companyName=&address1=123&city=Fake&state=

$state그 뒤에 의 값이 오고 St Miami FL커서는 줄의 시작 부분으로 돌아갑니다.

&urbanCode=&zip='

출력, 줄의 첫 번째 부분을 덮어쓰게 되어 이상하게 보입니다.

&urbanCode=&zip='ress1=123&city=Fake&state=St   Miami   FL

관련 정보