Before everyone freaks out and says this a duplicate, I would like to point out that while there are many questions about reading a file line by line, none that I've found are about storing an entire file into a single variable. Rather, most of the questions seem to be about performing some sort of operation on each line as they are being read in. As a example, consider the below:
#!/bin/sh
while IFS='' read -r line || [ -n "$line" ]; do
echo "$line"
done < file
I can't seem to implement this for my specific purpose. When I do the below:
#!/bin/sh
newline='
'
string=''
while IFS='' read -r line || [ -n "$line" ]; do
string="$string""$line""$newline"
done < file
echo "$string"
I almost get there, but now there is an extra newline at the end, and my string is not equal to my file. I've played with this for quite awhile, and I can't seem to read in the file such that my resulting string is completely identical to my file.
You're unconditionally adding a newline, with the string="$string""$line""$newline"
assignment.
read
returns true as long as it successfully reads a line, including a newline. Checking if $line
contains anything deals with the possible final line fragment. But when you process it, you need to not add the newline since it wasn't there to begin with. As long as there's no final line fragment, your script works fine.
It's probably easiest to fix by moving the [ -n "$line" ]
test outside the loop:
#!/bin/sh
newline='
'
string=
while IFS= read -r line; do
string="$string$line$newline"
done < "$1"
if [ "$line" ]; then
string="$string$line"
fi
echo "<$string>" # markers for clarity
Of course it might also be that the input file only has complete lines, and the extra newline is the one that echo
prints. Use printf "%s" "$string"
to print just the contents of the variable, without a newline or anything else. Some shells have echo -n
to inhibit the final newline, but that's nonstandard.