This is a script that helps us in creating a dhcpd.conf file.
sample inputs (ex. mac-tab-;-tab-IP)
DC:D3:21:75:61:90 ; 10.25.131.17
;
expected outputs
Host 27-48 { hardware ethernet DC:D3:21:75:61:90 ; fixed-address 10.25.131.17 ; }
#host 27-48 { hardware ethernet ; fixed-address ; }
Currently the line outputted is this:
Host 27-48 { hardware ethernet 00:16:6B:C8:3D:C9 ; fixed-address 10.25.129.185
Specific line in code I'm stuck on
outputLine="Host $((names[i]))-$((startingNumber+counter)) { hardware ethernet $first ; fixed-address $second"
If I try adding ; }
outputLine="Host $((names[i]))-$((startingNumber+counter)) { hardware ethernet $first ; fixed-address $second ; }"
I get this:
; } 27-48 { hardware ethernet 00:16:6B:C8:3D:C9 ; fixed-address 10.25.129.185
The issue is, whenever I append " ; }" to the end of the above line, it overwrites the beginning of the line. I've tried a few tricks to work around it, such as writing the above line to a string, and then trying to append to the string, but the same issue occurs. I had an idea to export the entire contents to a file, and re-reload the file into an array just so I can append, but it seems a little overkill.
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
As ruakh explains in a comment on the question, the problem was a CR (0xD
, \r
) character at the end of the value of variable $second
, which can be removed with the following parameter expansion: second="${second//$'\r'/}"
.
The rest of this answer explains the symptom and provides background information.
The issue is, whenever I append " ; }" to the end of the above line, it overwrites the beginning of the line.
"overwriting the beginning of a line" almost always points to an embedded CR (0xD
, \r
) character, which, when a string is printed to the terminal, gives the appearance of overwriting the start of the line:
$ 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.
It is only because the terminal interprets the CR (\r
) as "place the cursor at the start of the line" that d
- the remaining string after \r
- appears to "overwrite" the start of the already-printed part of the string.
You can visualize embedded CRs (and other control characters) with cat -et
, which represents them in caret notation as ^M
:
$ printf 'abc\rd' | cat -et
abc^Md # ^M represents a CR (\r)
As you can see, the d
didn't actually overwrite a
, the start of the string.
CR (\r
) instances are rarely used in the world of Unix text processing. If they do appear as part of text data, it is usually from Windows-originated sources that use CRLF (\r\n
) line endings rather than the Unix LF-only (\n
) line endings.
Often, the simplest approach is to simply remove the CR (\r
) instances before using the data with Unix utilities.
There are many, many existing answers that cover this territory, often recommending use of third-party utility dos2unix
, easily installable via the package managers of many platforms (e.g., sudo apt install dos2unix
on Ubunutu, or brew install dos2unix
on macOS, via Homebrew).
Alternatively,
for text already stored in a variable, use ruakh's approach based on parameter expansion; e.g., second="${second//$'\r'/}"
for files, solutions using standard utilities can act as a makeshift dos2unix
.