Iterate through multiline string line by line The Next CEO of Stack OverflowWhy is printf better than echo?Why is using a shell loop to process text considered bad practice?Are there naming conventions for variables in shell scripts?Why is my variable local in one 'while read' loop, but not in another seemingly similar loop?Understanding IFSWhat should interactive shells do in orphaned process groups?for loop to iterate through some file nth positionCron only occasionally sends e-mail on output and errorsIterate Through Sets of Command Arguments in Bashhow to iterate through files in directory excluding hidden filesStarting an interactive shell as an asynchronous process (signal delivery)Control characters in a terminal with an active foreground processhow to let sudo fork bash instead of sh?Multiline command : comment out one line

Is it correct to say moon starry nights?

Towers in the ocean; How deep can they be built?

Can I use the word “Senior” as part of a job title directly in German?

Calculate the Mean mean of two numbers

What was the first Unix version to run on a microcomputer?

How to properly draw diagonal line while using multicolumn inside tabular environment?

Can you teleport closer to a creature you are Frightened of?

Is there a way to save my career from absolute disaster?

What day is it again?

Is there an equivalent of cd - for cp or mv

Is it professional to write unrelated content in an almost-empty email?

(How) Could a medieval fantasy world survive a magic-induced "nuclear winter"?

Won the lottery - how do I keep the money?

Would a grinding machine be a simple and workable propulsion system for an interplanetary spacecraft?

Sulfuric acid symmetry point group

What was Carter Burkes job for "the company" in "Aliens"?

0-rank tensor vs vector in 1D

What flight has the highest ratio of timezone difference to flight time?

Traduction de « Life is a roller coaster »

Regression vs Random Forest - Combination of features

Prepend last line of stdin to entire stdin

Physiological effects of huge anime eyes

Deriving the equation for variance

What is the difference between Statistical Mechanics and Quantum Mechanics



Iterate through multiline string line by line



The Next CEO of Stack OverflowWhy is printf better than echo?Why is using a shell loop to process text considered bad practice?Are there naming conventions for variables in shell scripts?Why is my variable local in one 'while read' loop, but not in another seemingly similar loop?Understanding IFSWhat should interactive shells do in orphaned process groups?for loop to iterate through some file nth positionCron only occasionally sends e-mail on output and errorsIterate Through Sets of Command Arguments in Bashhow to iterate through files in directory excluding hidden filesStarting an interactive shell as an asynchronous process (signal delivery)Control characters in a terminal with an active foreground processhow to let sudo fork bash instead of sh?Multiline command : comment out one line










2















I would like to process a multiline string and iterate it line by line, in a POSIX shell (/bin/sh) on a BSD platform. Bash is not included in the base BSD-distribution and has a GPL license - so I am trying to make it universally work with /bin/sh instead.



I found a solution using a pipe, however in the regular /bin/sh shell, these a processed in a separate process, meaning the following does not work:



MULTILINE="`cat $SOMEFILE`"
SOMEVAR="original value"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
echo "this is a single line: $SINGLELINE"
echo "SOMEVAR is now: $SOMEVAR"
done

echo "Final SOMEVAR is unchanged: $SOMEVAR"


In the above example, it accomplishes what I want, except for the fact that changes to variables such as $SOMEVAR are not accessible outside the while loop.



My question: how can I accomplish something like the above without this restriction? Note that many solutions require Bash, whereas I am using the standard POSIX-shell /bin/sh.










share|improve this question
























  • Why can you not use bash? (add to your question)

    – ctrl-alt-delor
    10 hours ago











  • I can not reproduce your issue using /bin/sh on a BSD system. There is nothing in this code that would require bash.

    – Kusalananda
    10 hours ago












  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now. The example indeed does not require Bash.

    – Steiner
    10 hours ago











  • @Steiner In fact, it would have the same issue in bash.

    – Kusalananda
    10 hours ago






  • 3





    There is no Bourne shell on the BSDs. Nor is the Bourne shell standard. Do not conflate the Bourne shell with a POSIX-conformant sh.

    – JdeBP
    10 hours ago















2















I would like to process a multiline string and iterate it line by line, in a POSIX shell (/bin/sh) on a BSD platform. Bash is not included in the base BSD-distribution and has a GPL license - so I am trying to make it universally work with /bin/sh instead.



I found a solution using a pipe, however in the regular /bin/sh shell, these a processed in a separate process, meaning the following does not work:



MULTILINE="`cat $SOMEFILE`"
SOMEVAR="original value"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
echo "this is a single line: $SINGLELINE"
echo "SOMEVAR is now: $SOMEVAR"
done

echo "Final SOMEVAR is unchanged: $SOMEVAR"


In the above example, it accomplishes what I want, except for the fact that changes to variables such as $SOMEVAR are not accessible outside the while loop.



My question: how can I accomplish something like the above without this restriction? Note that many solutions require Bash, whereas I am using the standard POSIX-shell /bin/sh.










share|improve this question
























  • Why can you not use bash? (add to your question)

    – ctrl-alt-delor
    10 hours ago











  • I can not reproduce your issue using /bin/sh on a BSD system. There is nothing in this code that would require bash.

    – Kusalananda
    10 hours ago












  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now. The example indeed does not require Bash.

    – Steiner
    10 hours ago











  • @Steiner In fact, it would have the same issue in bash.

    – Kusalananda
    10 hours ago






  • 3





    There is no Bourne shell on the BSDs. Nor is the Bourne shell standard. Do not conflate the Bourne shell with a POSIX-conformant sh.

    – JdeBP
    10 hours ago













2












2








2








I would like to process a multiline string and iterate it line by line, in a POSIX shell (/bin/sh) on a BSD platform. Bash is not included in the base BSD-distribution and has a GPL license - so I am trying to make it universally work with /bin/sh instead.



I found a solution using a pipe, however in the regular /bin/sh shell, these a processed in a separate process, meaning the following does not work:



MULTILINE="`cat $SOMEFILE`"
SOMEVAR="original value"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
echo "this is a single line: $SINGLELINE"
echo "SOMEVAR is now: $SOMEVAR"
done

echo "Final SOMEVAR is unchanged: $SOMEVAR"


In the above example, it accomplishes what I want, except for the fact that changes to variables such as $SOMEVAR are not accessible outside the while loop.



My question: how can I accomplish something like the above without this restriction? Note that many solutions require Bash, whereas I am using the standard POSIX-shell /bin/sh.










share|improve this question
















I would like to process a multiline string and iterate it line by line, in a POSIX shell (/bin/sh) on a BSD platform. Bash is not included in the base BSD-distribution and has a GPL license - so I am trying to make it universally work with /bin/sh instead.



I found a solution using a pipe, however in the regular /bin/sh shell, these a processed in a separate process, meaning the following does not work:



MULTILINE="`cat $SOMEFILE`"
SOMEVAR="original value"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
echo "this is a single line: $SINGLELINE"
echo "SOMEVAR is now: $SOMEVAR"
done

echo "Final SOMEVAR is unchanged: $SOMEVAR"


In the above example, it accomplishes what I want, except for the fact that changes to variables such as $SOMEVAR are not accessible outside the while loop.



My question: how can I accomplish something like the above without this restriction? Note that many solutions require Bash, whereas I am using the standard POSIX-shell /bin/sh.







shell






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 10 hours ago







Steiner

















asked 11 hours ago









SteinerSteiner

908




908












  • Why can you not use bash? (add to your question)

    – ctrl-alt-delor
    10 hours ago











  • I can not reproduce your issue using /bin/sh on a BSD system. There is nothing in this code that would require bash.

    – Kusalananda
    10 hours ago












  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now. The example indeed does not require Bash.

    – Steiner
    10 hours ago











  • @Steiner In fact, it would have the same issue in bash.

    – Kusalananda
    10 hours ago






  • 3





    There is no Bourne shell on the BSDs. Nor is the Bourne shell standard. Do not conflate the Bourne shell with a POSIX-conformant sh.

    – JdeBP
    10 hours ago

















  • Why can you not use bash? (add to your question)

    – ctrl-alt-delor
    10 hours ago











  • I can not reproduce your issue using /bin/sh on a BSD system. There is nothing in this code that would require bash.

    – Kusalananda
    10 hours ago












  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now. The example indeed does not require Bash.

    – Steiner
    10 hours ago











  • @Steiner In fact, it would have the same issue in bash.

    – Kusalananda
    10 hours ago






  • 3





    There is no Bourne shell on the BSDs. Nor is the Bourne shell standard. Do not conflate the Bourne shell with a POSIX-conformant sh.

    – JdeBP
    10 hours ago
















Why can you not use bash? (add to your question)

– ctrl-alt-delor
10 hours ago





Why can you not use bash? (add to your question)

– ctrl-alt-delor
10 hours ago













I can not reproduce your issue using /bin/sh on a BSD system. There is nothing in this code that would require bash.

– Kusalananda
10 hours ago






I can not reproduce your issue using /bin/sh on a BSD system. There is nothing in this code that would require bash.

– Kusalananda
10 hours ago














My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now. The example indeed does not require Bash.

– Steiner
10 hours ago





My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now. The example indeed does not require Bash.

– Steiner
10 hours ago













@Steiner In fact, it would have the same issue in bash.

– Kusalananda
10 hours ago





@Steiner In fact, it would have the same issue in bash.

– Kusalananda
10 hours ago




3




3





There is no Bourne shell on the BSDs. Nor is the Bourne shell standard. Do not conflate the Bourne shell with a POSIX-conformant sh.

– JdeBP
10 hours ago





There is no Bourne shell on the BSDs. Nor is the Bourne shell standard. Do not conflate the Bourne shell with a POSIX-conformant sh.

– JdeBP
10 hours ago










3 Answers
3






active

oldest

votes


















4














You could use a here document:



while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done << EOF
$MULTILINE
EOF
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


Depending on the sh implementation, here-documents are implemented either as a deleted temporary file where the shell has stored the expansion of the variable followed by newline beforehand, or a pipe to which the shell feeds the expansion of the variable followed by newline. But in either case, except in the original Bourne shell (a shell that is no longer in use these days and is not a POSIX compliant shell), the command being redirected is not run in a subshell (as POSIX requires).



or you could use split+glob:



IFS='
' # split on newline only
set -o noglob
for SINGLELINE in $MULTILINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


But beware it skips empty lines.






share|improve this answer

























  • Both solutions worked well for me with /bin/sh. I think this solution is better than the one Kusalananda provided, though his answer is very informative too. I particularly like the for-loop solution since it probably is faster because it does not use read which is very slow. Thanks!

    – Steiner
    5 hours ago











  • @Steiner (Just had to quickly double check so that I didn't have a for-loop solution, which I fortunately did not have)

    – Kusalananda
    3 hours ago



















3














You would read directly from the file without the pipeline. This avoids running the while loop in a subshell, which allows you to see the changed value of $SOMEVALUE after the loop.



SOMEVAR="original value"

while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done <"$SOMEFILE"

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"


If you insist on having your $MULTILINE variable, then write that to a file and read it from there:



tmpfile=$(mktemp)
printf '%sn' "$MULTILINE" >"$tmpfile"

while ...; do
...
done <"$tmpfile"
rm "$tmpfile"


Also related:



  • Why is my variable local in one 'while read' loop, but not in another seemingly similar loop?

An answer to the above linked question also suggests writing your program in such a way that all uses of $SOMEVAR occurs within the subshell at the end of the pipeline:



MULTILINE=$(cat "$SOMEFILE")
SOMEVAR="original value"

printf '%sn' "$MULTILINE" |
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"



Also possibly related:



  • Why is using a shell loop to process text considered bad practice?

Other questions that may be of interest:



  • Why is printf better than echo?

  • Are there naming conventions for variables in shell scripts?





share|improve this answer

























  • Indeed this works, but requires a file to be fed to the while-loop. My actual code is more complex, and requires a modified multiline string to be fed to the while-loop. Your solution to write this multiline string to a temporary file works, but is there a solution that does not require writing a temporary file?

    – Steiner
    10 hours ago











  • @Steiner See update answer. There's not much else you could do without using features of specific shells.

    – Kusalananda
    10 hours ago











  • Thank you that answers my question. The suggestion at the end and the links provided are very helpful too!

    – Steiner
    10 hours ago











  • @Steiner ... except for using a here-document. Well, there's a thing I didn't think of :-)

    – Kusalananda
    3 hours ago


















0














It works for me :



$ cat bin/test
#! /bin/sh
SOMEFILE=$1
MULTILINE="`cat $SOMEFILE`"
SOMEVAR="blah"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
echo "this is a single line: $SINGLELINE"
echo "but accessing this var fails: $SOMEVAR"
done


and



$ bin/test bin/test
this is a single line: #! /bin/sh
but accessing this var fails: blah
this is a single line: SOMEFILE=$1
but accessing this var fails: blah
this is a single line: MULTILINE="`cat $SOMEFILE`"
but accessing this var fails: blah
this is a single line: SOMEVAR="blah"
but accessing this var fails: blah
this is a single line:
but accessing this var fails: blah
this is a single line: echo "$MULTILINE" | while IFS= read -r SINGLELINE
but accessing this var fails: blah
this is a single line: do
but accessing this var fails: blah
this is a single line: echo "this is a single line: $SINGLELINE"
but accessing this var fails: blah
this is a single line: echo "but accessing this var fails: $SOMEVAR"
but accessing this var fails: blah
this is a single line: done
but accessing this var fails: blah





share|improve this answer








New contributor




RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now.

    – Steiner
    10 hours ago











Your Answer








StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "106"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f509714%2fiterate-through-multiline-string-line-by-line%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes









4














You could use a here document:



while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done << EOF
$MULTILINE
EOF
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


Depending on the sh implementation, here-documents are implemented either as a deleted temporary file where the shell has stored the expansion of the variable followed by newline beforehand, or a pipe to which the shell feeds the expansion of the variable followed by newline. But in either case, except in the original Bourne shell (a shell that is no longer in use these days and is not a POSIX compliant shell), the command being redirected is not run in a subshell (as POSIX requires).



or you could use split+glob:



IFS='
' # split on newline only
set -o noglob
for SINGLELINE in $MULTILINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


But beware it skips empty lines.






share|improve this answer

























  • Both solutions worked well for me with /bin/sh. I think this solution is better than the one Kusalananda provided, though his answer is very informative too. I particularly like the for-loop solution since it probably is faster because it does not use read which is very slow. Thanks!

    – Steiner
    5 hours ago











  • @Steiner (Just had to quickly double check so that I didn't have a for-loop solution, which I fortunately did not have)

    – Kusalananda
    3 hours ago
















4














You could use a here document:



while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done << EOF
$MULTILINE
EOF
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


Depending on the sh implementation, here-documents are implemented either as a deleted temporary file where the shell has stored the expansion of the variable followed by newline beforehand, or a pipe to which the shell feeds the expansion of the variable followed by newline. But in either case, except in the original Bourne shell (a shell that is no longer in use these days and is not a POSIX compliant shell), the command being redirected is not run in a subshell (as POSIX requires).



or you could use split+glob:



IFS='
' # split on newline only
set -o noglob
for SINGLELINE in $MULTILINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


But beware it skips empty lines.






share|improve this answer

























  • Both solutions worked well for me with /bin/sh. I think this solution is better than the one Kusalananda provided, though his answer is very informative too. I particularly like the for-loop solution since it probably is faster because it does not use read which is very slow. Thanks!

    – Steiner
    5 hours ago











  • @Steiner (Just had to quickly double check so that I didn't have a for-loop solution, which I fortunately did not have)

    – Kusalananda
    3 hours ago














4












4








4







You could use a here document:



while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done << EOF
$MULTILINE
EOF
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


Depending on the sh implementation, here-documents are implemented either as a deleted temporary file where the shell has stored the expansion of the variable followed by newline beforehand, or a pipe to which the shell feeds the expansion of the variable followed by newline. But in either case, except in the original Bourne shell (a shell that is no longer in use these days and is not a POSIX compliant shell), the command being redirected is not run in a subshell (as POSIX requires).



or you could use split+glob:



IFS='
' # split on newline only
set -o noglob
for SINGLELINE in $MULTILINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


But beware it skips empty lines.






share|improve this answer















You could use a here document:



while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done << EOF
$MULTILINE
EOF
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


Depending on the sh implementation, here-documents are implemented either as a deleted temporary file where the shell has stored the expansion of the variable followed by newline beforehand, or a pipe to which the shell feeds the expansion of the variable followed by newline. But in either case, except in the original Bourne shell (a shell that is no longer in use these days and is not a POSIX compliant shell), the command being redirected is not run in a subshell (as POSIX requires).



or you could use split+glob:



IFS='
' # split on newline only
set -o noglob
for SINGLELINE in $MULTILINE
do
SOMEVAR="updated value"
printf '%sn' "this is a single line: $SINGLELINE"
printf '%sn' "SOMEVAR is now: $SOMEVAR"
done
printf '%sn' "Final SOMEVAL is still $SOMEVAR"


But beware it skips empty lines.







share|improve this answer














share|improve this answer



share|improve this answer








edited 3 hours ago

























answered 8 hours ago









Stéphane ChazelasStéphane Chazelas

312k57590946




312k57590946












  • Both solutions worked well for me with /bin/sh. I think this solution is better than the one Kusalananda provided, though his answer is very informative too. I particularly like the for-loop solution since it probably is faster because it does not use read which is very slow. Thanks!

    – Steiner
    5 hours ago











  • @Steiner (Just had to quickly double check so that I didn't have a for-loop solution, which I fortunately did not have)

    – Kusalananda
    3 hours ago


















  • Both solutions worked well for me with /bin/sh. I think this solution is better than the one Kusalananda provided, though his answer is very informative too. I particularly like the for-loop solution since it probably is faster because it does not use read which is very slow. Thanks!

    – Steiner
    5 hours ago











  • @Steiner (Just had to quickly double check so that I didn't have a for-loop solution, which I fortunately did not have)

    – Kusalananda
    3 hours ago

















Both solutions worked well for me with /bin/sh. I think this solution is better than the one Kusalananda provided, though his answer is very informative too. I particularly like the for-loop solution since it probably is faster because it does not use read which is very slow. Thanks!

– Steiner
5 hours ago





Both solutions worked well for me with /bin/sh. I think this solution is better than the one Kusalananda provided, though his answer is very informative too. I particularly like the for-loop solution since it probably is faster because it does not use read which is very slow. Thanks!

– Steiner
5 hours ago













@Steiner (Just had to quickly double check so that I didn't have a for-loop solution, which I fortunately did not have)

– Kusalananda
3 hours ago






@Steiner (Just had to quickly double check so that I didn't have a for-loop solution, which I fortunately did not have)

– Kusalananda
3 hours ago














3














You would read directly from the file without the pipeline. This avoids running the while loop in a subshell, which allows you to see the changed value of $SOMEVALUE after the loop.



SOMEVAR="original value"

while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done <"$SOMEFILE"

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"


If you insist on having your $MULTILINE variable, then write that to a file and read it from there:



tmpfile=$(mktemp)
printf '%sn' "$MULTILINE" >"$tmpfile"

while ...; do
...
done <"$tmpfile"
rm "$tmpfile"


Also related:



  • Why is my variable local in one 'while read' loop, but not in another seemingly similar loop?

An answer to the above linked question also suggests writing your program in such a way that all uses of $SOMEVAR occurs within the subshell at the end of the pipeline:



MULTILINE=$(cat "$SOMEFILE")
SOMEVAR="original value"

printf '%sn' "$MULTILINE" |
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"



Also possibly related:



  • Why is using a shell loop to process text considered bad practice?

Other questions that may be of interest:



  • Why is printf better than echo?

  • Are there naming conventions for variables in shell scripts?





share|improve this answer

























  • Indeed this works, but requires a file to be fed to the while-loop. My actual code is more complex, and requires a modified multiline string to be fed to the while-loop. Your solution to write this multiline string to a temporary file works, but is there a solution that does not require writing a temporary file?

    – Steiner
    10 hours ago











  • @Steiner See update answer. There's not much else you could do without using features of specific shells.

    – Kusalananda
    10 hours ago











  • Thank you that answers my question. The suggestion at the end and the links provided are very helpful too!

    – Steiner
    10 hours ago











  • @Steiner ... except for using a here-document. Well, there's a thing I didn't think of :-)

    – Kusalananda
    3 hours ago















3














You would read directly from the file without the pipeline. This avoids running the while loop in a subshell, which allows you to see the changed value of $SOMEVALUE after the loop.



SOMEVAR="original value"

while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done <"$SOMEFILE"

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"


If you insist on having your $MULTILINE variable, then write that to a file and read it from there:



tmpfile=$(mktemp)
printf '%sn' "$MULTILINE" >"$tmpfile"

while ...; do
...
done <"$tmpfile"
rm "$tmpfile"


Also related:



  • Why is my variable local in one 'while read' loop, but not in another seemingly similar loop?

An answer to the above linked question also suggests writing your program in such a way that all uses of $SOMEVAR occurs within the subshell at the end of the pipeline:



MULTILINE=$(cat "$SOMEFILE")
SOMEVAR="original value"

printf '%sn' "$MULTILINE" |
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"



Also possibly related:



  • Why is using a shell loop to process text considered bad practice?

Other questions that may be of interest:



  • Why is printf better than echo?

  • Are there naming conventions for variables in shell scripts?





share|improve this answer

























  • Indeed this works, but requires a file to be fed to the while-loop. My actual code is more complex, and requires a modified multiline string to be fed to the while-loop. Your solution to write this multiline string to a temporary file works, but is there a solution that does not require writing a temporary file?

    – Steiner
    10 hours ago











  • @Steiner See update answer. There's not much else you could do without using features of specific shells.

    – Kusalananda
    10 hours ago











  • Thank you that answers my question. The suggestion at the end and the links provided are very helpful too!

    – Steiner
    10 hours ago











  • @Steiner ... except for using a here-document. Well, there's a thing I didn't think of :-)

    – Kusalananda
    3 hours ago













3












3








3







You would read directly from the file without the pipeline. This avoids running the while loop in a subshell, which allows you to see the changed value of $SOMEVALUE after the loop.



SOMEVAR="original value"

while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done <"$SOMEFILE"

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"


If you insist on having your $MULTILINE variable, then write that to a file and read it from there:



tmpfile=$(mktemp)
printf '%sn' "$MULTILINE" >"$tmpfile"

while ...; do
...
done <"$tmpfile"
rm "$tmpfile"


Also related:



  • Why is my variable local in one 'while read' loop, but not in another seemingly similar loop?

An answer to the above linked question also suggests writing your program in such a way that all uses of $SOMEVAR occurs within the subshell at the end of the pipeline:



MULTILINE=$(cat "$SOMEFILE")
SOMEVAR="original value"

printf '%sn' "$MULTILINE" |
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"



Also possibly related:



  • Why is using a shell loop to process text considered bad practice?

Other questions that may be of interest:



  • Why is printf better than echo?

  • Are there naming conventions for variables in shell scripts?





share|improve this answer















You would read directly from the file without the pipeline. This avoids running the while loop in a subshell, which allows you to see the changed value of $SOMEVALUE after the loop.



SOMEVAR="original value"

while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done <"$SOMEFILE"

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"


If you insist on having your $MULTILINE variable, then write that to a file and read it from there:



tmpfile=$(mktemp)
printf '%sn' "$MULTILINE" >"$tmpfile"

while ...; do
...
done <"$tmpfile"
rm "$tmpfile"


Also related:



  • Why is my variable local in one 'while read' loop, but not in another seemingly similar loop?

An answer to the above linked question also suggests writing your program in such a way that all uses of $SOMEVAR occurs within the subshell at the end of the pipeline:



MULTILINE=$(cat "$SOMEFILE")
SOMEVAR="original value"

printf '%sn' "$MULTILINE" |
while IFS= read -r SINGLELINE
do
SOMEVAR="updated value"
printf 'this is a single line: %sn' "$SINGLELINE"
printf 'SOMEVAR is now: %sn' "$SOMEVAR"
done

printf 'Final SOMEVAR is: %sn' "$SOMEVAR"



Also possibly related:



  • Why is using a shell loop to process text considered bad practice?

Other questions that may be of interest:



  • Why is printf better than echo?

  • Are there naming conventions for variables in shell scripts?






share|improve this answer














share|improve this answer



share|improve this answer








edited 10 hours ago

























answered 10 hours ago









KusalanandaKusalananda

139k17259429




139k17259429












  • Indeed this works, but requires a file to be fed to the while-loop. My actual code is more complex, and requires a modified multiline string to be fed to the while-loop. Your solution to write this multiline string to a temporary file works, but is there a solution that does not require writing a temporary file?

    – Steiner
    10 hours ago











  • @Steiner See update answer. There's not much else you could do without using features of specific shells.

    – Kusalananda
    10 hours ago











  • Thank you that answers my question. The suggestion at the end and the links provided are very helpful too!

    – Steiner
    10 hours ago











  • @Steiner ... except for using a here-document. Well, there's a thing I didn't think of :-)

    – Kusalananda
    3 hours ago

















  • Indeed this works, but requires a file to be fed to the while-loop. My actual code is more complex, and requires a modified multiline string to be fed to the while-loop. Your solution to write this multiline string to a temporary file works, but is there a solution that does not require writing a temporary file?

    – Steiner
    10 hours ago











  • @Steiner See update answer. There's not much else you could do without using features of specific shells.

    – Kusalananda
    10 hours ago











  • Thank you that answers my question. The suggestion at the end and the links provided are very helpful too!

    – Steiner
    10 hours ago











  • @Steiner ... except for using a here-document. Well, there's a thing I didn't think of :-)

    – Kusalananda
    3 hours ago
















Indeed this works, but requires a file to be fed to the while-loop. My actual code is more complex, and requires a modified multiline string to be fed to the while-loop. Your solution to write this multiline string to a temporary file works, but is there a solution that does not require writing a temporary file?

– Steiner
10 hours ago





Indeed this works, but requires a file to be fed to the while-loop. My actual code is more complex, and requires a modified multiline string to be fed to the while-loop. Your solution to write this multiline string to a temporary file works, but is there a solution that does not require writing a temporary file?

– Steiner
10 hours ago













@Steiner See update answer. There's not much else you could do without using features of specific shells.

– Kusalananda
10 hours ago





@Steiner See update answer. There's not much else you could do without using features of specific shells.

– Kusalananda
10 hours ago













Thank you that answers my question. The suggestion at the end and the links provided are very helpful too!

– Steiner
10 hours ago





Thank you that answers my question. The suggestion at the end and the links provided are very helpful too!

– Steiner
10 hours ago













@Steiner ... except for using a here-document. Well, there's a thing I didn't think of :-)

– Kusalananda
3 hours ago





@Steiner ... except for using a here-document. Well, there's a thing I didn't think of :-)

– Kusalananda
3 hours ago











0














It works for me :



$ cat bin/test
#! /bin/sh
SOMEFILE=$1
MULTILINE="`cat $SOMEFILE`"
SOMEVAR="blah"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
echo "this is a single line: $SINGLELINE"
echo "but accessing this var fails: $SOMEVAR"
done


and



$ bin/test bin/test
this is a single line: #! /bin/sh
but accessing this var fails: blah
this is a single line: SOMEFILE=$1
but accessing this var fails: blah
this is a single line: MULTILINE="`cat $SOMEFILE`"
but accessing this var fails: blah
this is a single line: SOMEVAR="blah"
but accessing this var fails: blah
this is a single line:
but accessing this var fails: blah
this is a single line: echo "$MULTILINE" | while IFS= read -r SINGLELINE
but accessing this var fails: blah
this is a single line: do
but accessing this var fails: blah
this is a single line: echo "this is a single line: $SINGLELINE"
but accessing this var fails: blah
this is a single line: echo "but accessing this var fails: $SOMEVAR"
but accessing this var fails: blah
this is a single line: done
but accessing this var fails: blah





share|improve this answer








New contributor




RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now.

    – Steiner
    10 hours ago















0














It works for me :



$ cat bin/test
#! /bin/sh
SOMEFILE=$1
MULTILINE="`cat $SOMEFILE`"
SOMEVAR="blah"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
echo "this is a single line: $SINGLELINE"
echo "but accessing this var fails: $SOMEVAR"
done


and



$ bin/test bin/test
this is a single line: #! /bin/sh
but accessing this var fails: blah
this is a single line: SOMEFILE=$1
but accessing this var fails: blah
this is a single line: MULTILINE="`cat $SOMEFILE`"
but accessing this var fails: blah
this is a single line: SOMEVAR="blah"
but accessing this var fails: blah
this is a single line:
but accessing this var fails: blah
this is a single line: echo "$MULTILINE" | while IFS= read -r SINGLELINE
but accessing this var fails: blah
this is a single line: do
but accessing this var fails: blah
this is a single line: echo "this is a single line: $SINGLELINE"
but accessing this var fails: blah
this is a single line: echo "but accessing this var fails: $SOMEVAR"
but accessing this var fails: blah
this is a single line: done
but accessing this var fails: blah





share|improve this answer








New contributor




RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now.

    – Steiner
    10 hours ago













0












0








0







It works for me :



$ cat bin/test
#! /bin/sh
SOMEFILE=$1
MULTILINE="`cat $SOMEFILE`"
SOMEVAR="blah"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
echo "this is a single line: $SINGLELINE"
echo "but accessing this var fails: $SOMEVAR"
done


and



$ bin/test bin/test
this is a single line: #! /bin/sh
but accessing this var fails: blah
this is a single line: SOMEFILE=$1
but accessing this var fails: blah
this is a single line: MULTILINE="`cat $SOMEFILE`"
but accessing this var fails: blah
this is a single line: SOMEVAR="blah"
but accessing this var fails: blah
this is a single line:
but accessing this var fails: blah
this is a single line: echo "$MULTILINE" | while IFS= read -r SINGLELINE
but accessing this var fails: blah
this is a single line: do
but accessing this var fails: blah
this is a single line: echo "this is a single line: $SINGLELINE"
but accessing this var fails: blah
this is a single line: echo "but accessing this var fails: $SOMEVAR"
but accessing this var fails: blah
this is a single line: done
but accessing this var fails: blah





share|improve this answer








New contributor




RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.










It works for me :



$ cat bin/test
#! /bin/sh
SOMEFILE=$1
MULTILINE="`cat $SOMEFILE`"
SOMEVAR="blah"

echo "$MULTILINE" | while IFS= read -r SINGLELINE
do
echo "this is a single line: $SINGLELINE"
echo "but accessing this var fails: $SOMEVAR"
done


and



$ bin/test bin/test
this is a single line: #! /bin/sh
but accessing this var fails: blah
this is a single line: SOMEFILE=$1
but accessing this var fails: blah
this is a single line: MULTILINE="`cat $SOMEFILE`"
but accessing this var fails: blah
this is a single line: SOMEVAR="blah"
but accessing this var fails: blah
this is a single line:
but accessing this var fails: blah
this is a single line: echo "$MULTILINE" | while IFS= read -r SINGLELINE
but accessing this var fails: blah
this is a single line: do
but accessing this var fails: blah
this is a single line: echo "this is a single line: $SINGLELINE"
but accessing this var fails: blah
this is a single line: echo "but accessing this var fails: $SOMEVAR"
but accessing this var fails: blah
this is a single line: done
but accessing this var fails: blah






share|improve this answer








New contributor




RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this answer



share|improve this answer






New contributor




RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









answered 10 hours ago









RedocTsujRedocTsuj

1




1




New contributor




RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






RedocTsuj is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now.

    – Steiner
    10 hours ago

















  • My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now.

    – Steiner
    10 hours ago
















My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now.

– Steiner
10 hours ago





My apologies. In trying to create a minimized sample of the actual issue, i made some errors. I updated the code sample now, and it should reflect the problem correctly now.

– Steiner
10 hours ago

















draft saved

draft discarded
















































Thanks for contributing an answer to Unix & Linux Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f509714%2fiterate-through-multiline-string-line-by-line%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Благоевград Съдържание География | История | Население | Политика | Икономика и инфрастуктура | Здравеопазване | Образование и наука | Култура и забавления | Забележителности | Личности | Литература | Външни препратки | Бележки | Навигация42°01′18.99″ с. ш. 23°05′51″ и. д. / 42.021944° с. ш. 23.0975° и. д.*БлагоевградразширитередактиранеОфициален уебсайт на община БлагоевградНовинарски портал на Благоевград – blagoevgrad.euСайтове за БлагоевградНационален статистически институтdariknews.bgГригоровичъ, Викторъ. „Очеркъ путешествія по Европейской Турціи“. Москва, 1877.Стрезов, Георги. Два санджака от Източна Македония. Периодично списание на Българското книжовно дружество в Средец, кн. XXXVII и XXXVIII, 1891, стр. 18 – 19.Македония. Етнография и статистикаГаджанов, Димитър Г. Мюсюлманското население в Новоосвободените земи, в: Научна експедиция в Македония и Поморавието 1916, Военноиздателски комплекс „Св. Георги Победоносец“, Университетско издателство „Св. Климент Охридски“, София, 1993, стр. 244.паметник на незнайния четник&cd=18&hl=en&ct=clnk&client=firefox-a „История на днешен Благоевград“, взето от www.museumblg.com на 16 март 2010 г.„Справка за населението на град Благоевград, община Благоевград, област Благоевград, НСИ“„The population of all towns and villages in Blagoevgrad Province with 50 inhabitants or more according to census results and latest official estimates“„Ethnic composition, all places: 2011 census“История на Неврокопска епархия.Национален статистически институтМюсюлманско изповедание. Главно мюфтийствоНационален публичен регистър на храмовете в БългарияМюсюлманско изповедание. Главно мюфтийствоwww.dnes.bg Джамията в Благоевград не била паленаwww.sesc-bg.orgСписък на побратимени градовеТехническо побратимяванеГУМ грейва в цветовете на нощен Лас Вегас под името „Largo“, „МОЛ Благоевград“..., в. „Струма“grabo.bgwww.cinemaxbg.comррр4238731-067cad53a-0546-417b-a3d3-51e49b1d2232147736077147736077

What is the best defense strategy for Survival in Grand Theft Auto Online?What is JP used for in Grand Theft Auto Online?How do I setup a Crew HQ in Grand Theft Auto Online?How does stealth work in Grand Theft Auto Online?Is it possible to own more than 10 cars in Grand Theft Auto online?Where to find truck/trailers in Grand Theft Auto OnlineWhat are some of the best missions to do on Grand Theft Auto 5 onlineFastest Car in Grand Theft Auto V PCHow to setup a Crew vs Crew online session in Grand Theft Auto Online?Grand theft auto 5 crossplayingRestart Grand Theft Auto V Online?

How does Billy Russo acquire his 'Jigsaw' mask? Unicorn Meta Zoo #1: Why another podcast? Announcing the arrival of Valued Associate #679: Cesar Manara Favourite questions and answers from the 1st quarter of 2019Why does Bane wear the mask?Why does Kylo Ren wear a mask?Why did Captain America remove his mask while fighting Batroc the Leaper?How did the OA acquire her wisdom?Is Billy Breckenridge gay?How does Adrian Toomes hide his earnings from the IRS?What is the state of affairs on Nootka Sound by the end of season 1?How did Tia Dalma acquire Captain Barbossa's body?How is one “Deemed Worthy”, to acquire the Greatsword “Dawn”?How did Karen acquire the handgun?