1

I am trying to loop over a variable which contains newlines in a POSIX compatible way.

The following works:

echo "$REQUIRE_PURPOSE" | while IFS= read -r line ; do
  echo "$line"
done

but the piping spawns another shell.

I then tried:

OLDIFS="$IFS"
IFS='
'
for line in "$REQUIRE_PURPOSE"; do
  echo "$line"
done
IFS="$OLDIFS"

But it just prints the content of "$REQUIRE_PURPOSE"

I also tried:

while IFS= read -r line ; do
  echo "$line"
done <<< "$REQUIRE_PURPOSE"

but also here it does not work.

Example:

echo "$REQUIRE_PURPOSE"
echo "---"
while IFS= read -r line ; do echo "$line"; done <<< "$REQUIRE_PURPOSE"

generates:

uuu
iii
Digital Signature
---
uuuniiinDigital Signature

or

00000000  75 75 75 0a 69 69 69 0a  44 69 67 69 74 61 6c 20  |uuu.iii.Digital |
00000010  53 69 67 6e 61 74 75 72  65 0a 2d 2d 2d 0a 31 20  |Signature.---.1 |
00000020  75 75 75 6e 69 69 69 6e  44 69 67 69 74 61 6c 20  |uuuniiinDigital |
00000030  53 69 67 6e 61 74 75 72  65 0a 75 75 75 0a 69 69  |Signature.uuu.ii|
00000040  69 0a 44 69 67 69 74 61  6c 20 53 69 67 6e 61 74  |i.Digital Signat|
00000050  75 72 65 0a                                       |ure.|
00000054

Any idea?

8
  • The code while ... do ... done <<< "$REQUIRE_PURPOSE" works for me. What problem do you have? Commented Jun 17, 2022 at 12:27
  • @bodo I get just one loop iteration. macOS with bash 5.1.16(1)-release (I added the example to the question) Commented Jun 17, 2022 at 12:36
  • I successfully tested it with Git Bash on Windows and bash on Linux (armv7l, Raspberry PI). How do you set the value of REQUIRE_PURPOSE? Can you add code that sets the variable? Did you intentionally use read -a instead of read -r in the code below "Example:"? Commented Jun 17, 2022 at 12:44
  • Does your variable contain a sequence of \ and n instead of real linefeed characters? Commented Jun 17, 2022 at 12:45
  • @Bodo: according to hexdump is 0a (nl) Commented Jun 17, 2022 at 12:49

2 Answers 2

0

The option to read you need is -a. It will parse the input by IFS into the array:

read -a lines <<<"$REQUIRE_PURPOSE"
for i in "${lines[@]}"
do
    echo "$i"
done
3
  • Is there a POSIX compatible way? Commented Jun 17, 2022 at 12:27
  • ITYM IFS=$'\n' read -a arr -d '' <<< "$var", since you need to have the -d separator distinct from the IFS separator. Though you'd probably be better off using readarray/mapfile there, just mapfile -t arr <<< "$var" would do. Commented Jun 17, 2022 at 13:42
  • @Matteo, <<< already isn't standard. Also note that it adds a trailing newline, so you might get an extra one at the end. Commented Jun 17, 2022 at 13:43
0

You can do this with parameter expansion (S.2.6.2) and command substitution (S.2.6.3) inside an unquoted HereDoc (S2.7.4):

VAR="$(echo Line1; echo Line2; echo EOF; echo "HereDoc continues."; echo Line5)"
while read line; do
 printf "Line-%s-END\n" "$line"
done << EOF
$VAR
EOF
while read line; do
 printf "Line-%s-END\n" "$line"
done << EOF
$(
 echo Line1
 echo Line2
 echo EOF
 echo "The HereDoc continues."
 echo Line5
)
EOF

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.