thi*_*not 4 string bash line-endings
这是一个帮助我们创建 dhcpd.conf 文件的脚本。
示例输入(例如 mac-tab-;-tab-IP)
DC:D3:21:75:61:90 ; 10.25.131.17
;
Run Code Online (Sandbox Code Playgroud)
预期产出
Host 27-48 { hardware ethernet DC:D3:21:75:61:90 ; fixed-address 10.25.131.17 ; }
#host 27-48 { hardware ethernet ; fixed-address ; }
Run Code Online (Sandbox Code Playgroud)
目前输出的行是这样的:
Host 27-48 { hardware ethernet 00:16:6B:C8:3D:C9 ; fixed-address 10.25.129.185
Run Code Online (Sandbox Code Playgroud)
我被困在代码中的特定行
outputLine="Host $((names[i]))-$((startingNumber+counter)) { hardware ethernet $first ; fixed-address $second"
Run Code Online (Sandbox Code Playgroud)
如果我尝试添加 ; }
outputLine="Host $((names[i]))-$((startingNumber+counter)) { hardware ethernet $first ; fixed-address $second ; }"
Run Code Online (Sandbox Code Playgroud)
我明白了:
; } 27-48 { hardware ethernet 00:16:6B:C8:3D:C9 ; fixed-address 10.25.129.185
Run Code Online (Sandbox Code Playgroud)
问题是,每当我将“;}”附加到上一行的末尾时,它就会覆盖该行的开头。我尝试了一些技巧来解决这个问题,例如将上面的行写入字符串,然后尝试附加到该字符串,但出现了同样的问题。我有一个想法将整个内容导出到一个文件,然后将文件重新加载到一个数组中,以便我可以追加,但这似乎有点矫枉过正。
for ((j=1; j<=${sizes[i]}; j++ )); do
#split line, read split as two entries for an arrIN
IN=(${line[counter+1]})
arrIN=(${IN//;/ })
first="${arrIN[0]}"
second=${arrIN[1]}
if [ ${lineSize[counter+1]} -gt 5 ]
then
#sed 's/$/ ; }/' $outputLine > newoutputLine
outputLine="Host $((names[i]))-$((startingNumber+counter)) { hardware ethernet $first ; fixed-address $second"
echo $outputLine
else
echo "#host $((names[i])) $((startingNumber+counter)) { hardware ethernet ; fixed-address ; }"
fi
counter=$((counter+1))
done
Run Code Online (Sandbox Code Playgroud)
正如ruakh在对该问题的评论中所解释的那样,问题是变量值末尾的CR ( 0xD,\r$second ) 字符,可以通过以下参数扩展将其删除:second="${second//$'\r'/}"。
本答案的其余部分解释了症状并提供了背景信息。
问题是,每当我将“;}”附加到上一行的末尾时,它就会覆盖该行的开头。
“覆盖行的开头”几乎总是指向嵌入的CR ( 0xD, \r) 字符,当将字符串打印到终端时,该字符会显示覆盖行的开头的外观:
$ printf 'abc\rd' # `printf '\r'` produces a CR
dbc # It LOOKS LIKE 'd' replaced 'a', but that's an artifact of printing to the terminal.
Run Code Online (Sandbox Code Playgroud)
只是因为终端将 CR ( \r) 解释为“将光标放在行的开头”,d之后的剩余字符串\r似乎“覆盖”了字符串已打印部分的开头。
您可以使用 可视化嵌入的 CR(和其他控制字符)cat -et ,它以脱字符号表示它们^M:
$ printf 'abc\rd' | cat -et
abc^Md # ^M represents a CR (\r)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,d实际上并没有覆盖 a字符串的开头。
CR ( ) 实例在Unix文本处理\r领域很少使用。如果它们确实作为文本数据的一部分出现,则通常来自使用 CRLF ( ) 行结尾的Windows源,而不是 Unix 仅 LF ( ) 行结尾。\r\n\n
通常,最简单的方法是在通过 Unix 实用程序使用数据之前简单地删除CR( \r) 实例。
有很多很多现有的答案涵盖了这个领域,通常建议使用第三方实用程序dos2unix,可以通过许多平台的包管理器轻松安装(例如,sudo apt install dos2unix在 Ubunutu 上,或brew install dos2unix在 macOS 上,通过Homebrew)。
或者,
对于已经存储在变量中的文本,使用ruakh基于参数扩展的方法;例如, second="${second//$'\r'/}"
对于文件,使用标准实用程序的解决方案可以充当临时方案dos2unix。