在调试脚本时,我终于找到了原因,但我不明白为什么。
一个制表符分隔的文本文件示例包含:
$ 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 bash,版本 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