Here my script:
#!/bin/bash
read -r -d '' content << VAR
one
two
three
{"foo":"bar"}
{cron":"0 1 * * *"}
VAR
for line in $content; do
echo "==| ${line}"
done
without line {cron":"0 1 * * *"}
it works perfectly and produces correct output:
==| one
==| two
==| three
==| {"foo":"bar"}
but with line {cron":"0 1 * * *"}
it prints corrupted output:
==| one
==| two
==| three
==| {"foo":"bar"}
==| {cron":"0
==| 1
==| LICENSE
==| README.md
==| ed
==| y.sh
==| LICENSE
==| README.md
==| ed
==| y.sh
==| *"}
I'm running this script on macOS
.
CodePudding user response:
The correct way to write this script is a while
loop.
while IFS= read -r line; do
printf '%s\n' "$line"
done <<'EOF'
one
two
three
{"foo":"bar"}
{cron":"0 1 * * *"}
EOF
At the very least, you don't need read
to set the value of content
:
content='one
two
three
{"foo":"bar"}
{cron":"0 1 * * *"}'
but iterating over a file using a for
loop is full of problems. See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)? and Why you don't read lines with "for"
CodePudding user response:
Edit: The correct way is to use a while-loop instead of a for-loop. See other answers.
The "for line"-loop splits at whitespace. The first unwanted whitespace is the space in cron line between "0" and "1". The "junk" in the output are the script's command line arguments? At least my tests look like they are.
To avoid splitting at whitespace, use the variable IFS. Set it to "newline".
IFS=$'\n'
read -r -d '' content << VAR
one
two
three
{"foo":"bar"}
{"cron":"0 1 * * *"}
VAR
for line in $content; do
echo "==| ${line}"
done