Read from file then use for to split fields but honor quotes

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












2















This what I am trying to get in a bash shell script:



for a in "1" "2 3" "4 5 6"
do
echo "a: $a"
done
a: 1
a: 2 3
a: 4 5 6


But the quotes are treated differently when you use a variable:



echo ""1" "2 3" "4 5 6"" > a.txt

cat a.txt
"1" "2 3" "4 5 6"

read aline < a.txt


If you double-quote the variable, you get this:



for b in "$aline"
do
echo "b: $b"
done
b: "1" "2 3" "4 5 6"


And without quotes you get this:



for b in $aline
do
echo "b: $b"
done
b: "1"
b: "2
b: 3"
b: "4
b: 5
b: 6"


Is there a way to get the for to process the contents of the variable as in the first example?










share|improve this question
























  • Is there another issue that makes you ask this question? Do you have another problem that requires you to disable the shell's standard quote removal, which happens during the evaluation of a command?

    – Kusalananda
    Feb 21 at 6:43











  • @Kusalananda yeah, the OP said something to the effect that they simplified the example too much and here were the real thing, but it was cut short at the ":", and the message was immediately deleted. Let's hope that nothing bad happened to him <;-

    – mosvy
    Feb 21 at 7:19












  • This is my first time posting a question on this forum, so working out my bugs around posting/commenting. The first answer I got from mosvy gave me enough to work out a solution. The "set -- " seemed to be losing fields. It doesn't like having '#Mi' (no quotes) as one of the fields but once I realized that, I just ran it through sed and now I'm getting what I want. Thanks for the help.

    – Linus Hicks
    Feb 21 at 7:46











  • @LinusHicks If you're happy with one or several of the answers, upvote them. If one is solving your issue, accepting it would be the best way of saying "Thank You!" Accepting an answer also indicates to future readers that the answer actually solved the problem.

    – Kusalananda
    Feb 21 at 8:10















2















This what I am trying to get in a bash shell script:



for a in "1" "2 3" "4 5 6"
do
echo "a: $a"
done
a: 1
a: 2 3
a: 4 5 6


But the quotes are treated differently when you use a variable:



echo ""1" "2 3" "4 5 6"" > a.txt

cat a.txt
"1" "2 3" "4 5 6"

read aline < a.txt


If you double-quote the variable, you get this:



for b in "$aline"
do
echo "b: $b"
done
b: "1" "2 3" "4 5 6"


And without quotes you get this:



for b in $aline
do
echo "b: $b"
done
b: "1"
b: "2
b: 3"
b: "4
b: 5
b: 6"


Is there a way to get the for to process the contents of the variable as in the first example?










share|improve this question
























  • Is there another issue that makes you ask this question? Do you have another problem that requires you to disable the shell's standard quote removal, which happens during the evaluation of a command?

    – Kusalananda
    Feb 21 at 6:43











  • @Kusalananda yeah, the OP said something to the effect that they simplified the example too much and here were the real thing, but it was cut short at the ":", and the message was immediately deleted. Let's hope that nothing bad happened to him <;-

    – mosvy
    Feb 21 at 7:19












  • This is my first time posting a question on this forum, so working out my bugs around posting/commenting. The first answer I got from mosvy gave me enough to work out a solution. The "set -- " seemed to be losing fields. It doesn't like having '#Mi' (no quotes) as one of the fields but once I realized that, I just ran it through sed and now I'm getting what I want. Thanks for the help.

    – Linus Hicks
    Feb 21 at 7:46











  • @LinusHicks If you're happy with one or several of the answers, upvote them. If one is solving your issue, accepting it would be the best way of saying "Thank You!" Accepting an answer also indicates to future readers that the answer actually solved the problem.

    – Kusalananda
    Feb 21 at 8:10













2












2








2








This what I am trying to get in a bash shell script:



for a in "1" "2 3" "4 5 6"
do
echo "a: $a"
done
a: 1
a: 2 3
a: 4 5 6


But the quotes are treated differently when you use a variable:



echo ""1" "2 3" "4 5 6"" > a.txt

cat a.txt
"1" "2 3" "4 5 6"

read aline < a.txt


If you double-quote the variable, you get this:



for b in "$aline"
do
echo "b: $b"
done
b: "1" "2 3" "4 5 6"


And without quotes you get this:



for b in $aline
do
echo "b: $b"
done
b: "1"
b: "2
b: 3"
b: "4
b: 5
b: 6"


Is there a way to get the for to process the contents of the variable as in the first example?










share|improve this question
















This what I am trying to get in a bash shell script:



for a in "1" "2 3" "4 5 6"
do
echo "a: $a"
done
a: 1
a: 2 3
a: 4 5 6


But the quotes are treated differently when you use a variable:



echo ""1" "2 3" "4 5 6"" > a.txt

cat a.txt
"1" "2 3" "4 5 6"

read aline < a.txt


If you double-quote the variable, you get this:



for b in "$aline"
do
echo "b: $b"
done
b: "1" "2 3" "4 5 6"


And without quotes you get this:



for b in $aline
do
echo "b: $b"
done
b: "1"
b: "2
b: 3"
b: "4
b: 5
b: 6"


Is there a way to get the for to process the contents of the variable as in the first example?







bash for






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 21 at 12:35









filbranden

10.6k21646




10.6k21646










asked Feb 21 at 2:40









Linus HicksLinus Hicks

111




111












  • Is there another issue that makes you ask this question? Do you have another problem that requires you to disable the shell's standard quote removal, which happens during the evaluation of a command?

    – Kusalananda
    Feb 21 at 6:43











  • @Kusalananda yeah, the OP said something to the effect that they simplified the example too much and here were the real thing, but it was cut short at the ":", and the message was immediately deleted. Let's hope that nothing bad happened to him <;-

    – mosvy
    Feb 21 at 7:19












  • This is my first time posting a question on this forum, so working out my bugs around posting/commenting. The first answer I got from mosvy gave me enough to work out a solution. The "set -- " seemed to be losing fields. It doesn't like having '#Mi' (no quotes) as one of the fields but once I realized that, I just ran it through sed and now I'm getting what I want. Thanks for the help.

    – Linus Hicks
    Feb 21 at 7:46











  • @LinusHicks If you're happy with one or several of the answers, upvote them. If one is solving your issue, accepting it would be the best way of saying "Thank You!" Accepting an answer also indicates to future readers that the answer actually solved the problem.

    – Kusalananda
    Feb 21 at 8:10

















  • Is there another issue that makes you ask this question? Do you have another problem that requires you to disable the shell's standard quote removal, which happens during the evaluation of a command?

    – Kusalananda
    Feb 21 at 6:43











  • @Kusalananda yeah, the OP said something to the effect that they simplified the example too much and here were the real thing, but it was cut short at the ":", and the message was immediately deleted. Let's hope that nothing bad happened to him <;-

    – mosvy
    Feb 21 at 7:19












  • This is my first time posting a question on this forum, so working out my bugs around posting/commenting. The first answer I got from mosvy gave me enough to work out a solution. The "set -- " seemed to be losing fields. It doesn't like having '#Mi' (no quotes) as one of the fields but once I realized that, I just ran it through sed and now I'm getting what I want. Thanks for the help.

    – Linus Hicks
    Feb 21 at 7:46











  • @LinusHicks If you're happy with one or several of the answers, upvote them. If one is solving your issue, accepting it would be the best way of saying "Thank You!" Accepting an answer also indicates to future readers that the answer actually solved the problem.

    – Kusalananda
    Feb 21 at 8:10
















Is there another issue that makes you ask this question? Do you have another problem that requires you to disable the shell's standard quote removal, which happens during the evaluation of a command?

– Kusalananda
Feb 21 at 6:43





Is there another issue that makes you ask this question? Do you have another problem that requires you to disable the shell's standard quote removal, which happens during the evaluation of a command?

– Kusalananda
Feb 21 at 6:43













@Kusalananda yeah, the OP said something to the effect that they simplified the example too much and here were the real thing, but it was cut short at the ":", and the message was immediately deleted. Let's hope that nothing bad happened to him <;-

– mosvy
Feb 21 at 7:19






@Kusalananda yeah, the OP said something to the effect that they simplified the example too much and here were the real thing, but it was cut short at the ":", and the message was immediately deleted. Let's hope that nothing bad happened to him <;-

– mosvy
Feb 21 at 7:19














This is my first time posting a question on this forum, so working out my bugs around posting/commenting. The first answer I got from mosvy gave me enough to work out a solution. The "set -- " seemed to be losing fields. It doesn't like having '#Mi' (no quotes) as one of the fields but once I realized that, I just ran it through sed and now I'm getting what I want. Thanks for the help.

– Linus Hicks
Feb 21 at 7:46





This is my first time posting a question on this forum, so working out my bugs around posting/commenting. The first answer I got from mosvy gave me enough to work out a solution. The "set -- " seemed to be losing fields. It doesn't like having '#Mi' (no quotes) as one of the fields but once I realized that, I just ran it through sed and now I'm getting what I want. Thanks for the help.

– Linus Hicks
Feb 21 at 7:46













@LinusHicks If you're happy with one or several of the answers, upvote them. If one is solving your issue, accepting it would be the best way of saying "Thank You!" Accepting an answer also indicates to future readers that the answer actually solved the problem.

– Kusalananda
Feb 21 at 8:10





@LinusHicks If you're happy with one or several of the answers, upvote them. If one is solving your issue, accepting it would be the best way of saying "Thank You!" Accepting an answer also indicates to future readers that the answer actually solved the problem.

– Kusalananda
Feb 21 at 8:10










2 Answers
2






active

oldest

votes


















2














If you're OK with having the whole package (variable/arithmetic/command expansion, globbing, etc) on top of quote processing, this will do:



echo '"a b" "x y"' >a.txt

eval "set -- $(<a.txt)"
for b do
printf 'b: %sn' "$b"
done

b: a b
b: x y


Change the $(<a.txt) to $(cat a.txt) if you want it to work in a regular shell, not just bash (or other advanced shells like zsh or ksh). You could only use this if you're sure you can control the content of a.txt, otherwise it will be trivial to exploit your script via splitting with ;, command expansion, etc.



However, if you just want to pass those arguments to a command, you can use xargs, which will just process the quotes, without doing any expansion:



xargs <a.txt printf 'b: %sn'


But xargs will only work with external commands, not with shell functions, will ignore backslashes inside double quotes just like inside single quotes, and won't be able to parse multiline strings.



If these latter limitations are OK, you can still use xargs as a quote parser via a wrapper or an array:



mapfile -t args < <(xargs <a.txt printf '%sn')
for b in "$args[@]"; do
printf 'b: %sn' "$b"
done





share|improve this answer

























  • Note that $(<...) is a ksh operator, copied by zsh and bash (though bash still forks a process, so only save the cat execution there when using it). See Understanding Bash's Read-a-File Command Substitution for details.

    – Stéphane Chazelas
    Feb 21 at 6:33











  • @StéphaneChazelas included both suggestions.

    – mosvy
    Feb 21 at 6:45











  • @StéphaneChazelas no, it's not: printf '"anb" c' | xargs => xargs: unterminated quote, xargs: unmatched double quote, etc. Also the standard says: A string of zero or more non-double-quote ( '"') characters and non- <newline> characters can be quoted by enclosing them in double-quotes. Same thing for single quotes.

    – mosvy
    Feb 21 at 7:11












  • Oh yes, you're right, for xargs a newline is quoted with backslash only. I forgot about that, sorry.

    – Stéphane Chazelas
    Feb 21 at 7:15


















1














If instead of bash you're using ksh93 (ksh93 is the shell bash tries to mimic anyway), you could use the -S option of its read builtin which is to read csv (so understands csv-style quoting):



IFS=" " read -rSA array < a.txt
printf 'a: %sn' "$array[@]"


With zsh, you could use it's z parameter expansion flag which is used to tokenise the content of a variable as if it was zsh code (and so understand quoting as zsh would, but not do the code evaluation that eval would do) along with the Q parameter expansion flag to remove one layer of quoting:



IFS= read -r line < a.txt
printf 'a: %sn' "$(Q@)$(z)line"


(the @ parameter expansion flag is to preserve empty elements, reminiscent of ksh's $array[@] behaviour).



If a.txt contains more than one line, with zsh you can replace the read command with content=$(<a.txt) and with ksh93 use read in a while loop (each read invocation potentially reading more than one line if a quoted string spans several line).






share|improve this answer
























    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%2f501994%2fread-from-file-then-use-for-to-split-fields-but-honor-quotes%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    If you're OK with having the whole package (variable/arithmetic/command expansion, globbing, etc) on top of quote processing, this will do:



    echo '"a b" "x y"' >a.txt

    eval "set -- $(<a.txt)"
    for b do
    printf 'b: %sn' "$b"
    done

    b: a b
    b: x y


    Change the $(<a.txt) to $(cat a.txt) if you want it to work in a regular shell, not just bash (or other advanced shells like zsh or ksh). You could only use this if you're sure you can control the content of a.txt, otherwise it will be trivial to exploit your script via splitting with ;, command expansion, etc.



    However, if you just want to pass those arguments to a command, you can use xargs, which will just process the quotes, without doing any expansion:



    xargs <a.txt printf 'b: %sn'


    But xargs will only work with external commands, not with shell functions, will ignore backslashes inside double quotes just like inside single quotes, and won't be able to parse multiline strings.



    If these latter limitations are OK, you can still use xargs as a quote parser via a wrapper or an array:



    mapfile -t args < <(xargs <a.txt printf '%sn')
    for b in "$args[@]"; do
    printf 'b: %sn' "$b"
    done





    share|improve this answer

























    • Note that $(<...) is a ksh operator, copied by zsh and bash (though bash still forks a process, so only save the cat execution there when using it). See Understanding Bash's Read-a-File Command Substitution for details.

      – Stéphane Chazelas
      Feb 21 at 6:33











    • @StéphaneChazelas included both suggestions.

      – mosvy
      Feb 21 at 6:45











    • @StéphaneChazelas no, it's not: printf '"anb" c' | xargs => xargs: unterminated quote, xargs: unmatched double quote, etc. Also the standard says: A string of zero or more non-double-quote ( '"') characters and non- <newline> characters can be quoted by enclosing them in double-quotes. Same thing for single quotes.

      – mosvy
      Feb 21 at 7:11












    • Oh yes, you're right, for xargs a newline is quoted with backslash only. I forgot about that, sorry.

      – Stéphane Chazelas
      Feb 21 at 7:15















    2














    If you're OK with having the whole package (variable/arithmetic/command expansion, globbing, etc) on top of quote processing, this will do:



    echo '"a b" "x y"' >a.txt

    eval "set -- $(<a.txt)"
    for b do
    printf 'b: %sn' "$b"
    done

    b: a b
    b: x y


    Change the $(<a.txt) to $(cat a.txt) if you want it to work in a regular shell, not just bash (or other advanced shells like zsh or ksh). You could only use this if you're sure you can control the content of a.txt, otherwise it will be trivial to exploit your script via splitting with ;, command expansion, etc.



    However, if you just want to pass those arguments to a command, you can use xargs, which will just process the quotes, without doing any expansion:



    xargs <a.txt printf 'b: %sn'


    But xargs will only work with external commands, not with shell functions, will ignore backslashes inside double quotes just like inside single quotes, and won't be able to parse multiline strings.



    If these latter limitations are OK, you can still use xargs as a quote parser via a wrapper or an array:



    mapfile -t args < <(xargs <a.txt printf '%sn')
    for b in "$args[@]"; do
    printf 'b: %sn' "$b"
    done





    share|improve this answer

























    • Note that $(<...) is a ksh operator, copied by zsh and bash (though bash still forks a process, so only save the cat execution there when using it). See Understanding Bash's Read-a-File Command Substitution for details.

      – Stéphane Chazelas
      Feb 21 at 6:33











    • @StéphaneChazelas included both suggestions.

      – mosvy
      Feb 21 at 6:45











    • @StéphaneChazelas no, it's not: printf '"anb" c' | xargs => xargs: unterminated quote, xargs: unmatched double quote, etc. Also the standard says: A string of zero or more non-double-quote ( '"') characters and non- <newline> characters can be quoted by enclosing them in double-quotes. Same thing for single quotes.

      – mosvy
      Feb 21 at 7:11












    • Oh yes, you're right, for xargs a newline is quoted with backslash only. I forgot about that, sorry.

      – Stéphane Chazelas
      Feb 21 at 7:15













    2












    2








    2







    If you're OK with having the whole package (variable/arithmetic/command expansion, globbing, etc) on top of quote processing, this will do:



    echo '"a b" "x y"' >a.txt

    eval "set -- $(<a.txt)"
    for b do
    printf 'b: %sn' "$b"
    done

    b: a b
    b: x y


    Change the $(<a.txt) to $(cat a.txt) if you want it to work in a regular shell, not just bash (or other advanced shells like zsh or ksh). You could only use this if you're sure you can control the content of a.txt, otherwise it will be trivial to exploit your script via splitting with ;, command expansion, etc.



    However, if you just want to pass those arguments to a command, you can use xargs, which will just process the quotes, without doing any expansion:



    xargs <a.txt printf 'b: %sn'


    But xargs will only work with external commands, not with shell functions, will ignore backslashes inside double quotes just like inside single quotes, and won't be able to parse multiline strings.



    If these latter limitations are OK, you can still use xargs as a quote parser via a wrapper or an array:



    mapfile -t args < <(xargs <a.txt printf '%sn')
    for b in "$args[@]"; do
    printf 'b: %sn' "$b"
    done





    share|improve this answer















    If you're OK with having the whole package (variable/arithmetic/command expansion, globbing, etc) on top of quote processing, this will do:



    echo '"a b" "x y"' >a.txt

    eval "set -- $(<a.txt)"
    for b do
    printf 'b: %sn' "$b"
    done

    b: a b
    b: x y


    Change the $(<a.txt) to $(cat a.txt) if you want it to work in a regular shell, not just bash (or other advanced shells like zsh or ksh). You could only use this if you're sure you can control the content of a.txt, otherwise it will be trivial to exploit your script via splitting with ;, command expansion, etc.



    However, if you just want to pass those arguments to a command, you can use xargs, which will just process the quotes, without doing any expansion:



    xargs <a.txt printf 'b: %sn'


    But xargs will only work with external commands, not with shell functions, will ignore backslashes inside double quotes just like inside single quotes, and won't be able to parse multiline strings.



    If these latter limitations are OK, you can still use xargs as a quote parser via a wrapper or an array:



    mapfile -t args < <(xargs <a.txt printf '%sn')
    for b in "$args[@]"; do
    printf 'b: %sn' "$b"
    done






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Feb 21 at 6:40

























    answered Feb 21 at 4:07









    mosvymosvy

    8,2871732




    8,2871732












    • Note that $(<...) is a ksh operator, copied by zsh and bash (though bash still forks a process, so only save the cat execution there when using it). See Understanding Bash's Read-a-File Command Substitution for details.

      – Stéphane Chazelas
      Feb 21 at 6:33











    • @StéphaneChazelas included both suggestions.

      – mosvy
      Feb 21 at 6:45











    • @StéphaneChazelas no, it's not: printf '"anb" c' | xargs => xargs: unterminated quote, xargs: unmatched double quote, etc. Also the standard says: A string of zero or more non-double-quote ( '"') characters and non- <newline> characters can be quoted by enclosing them in double-quotes. Same thing for single quotes.

      – mosvy
      Feb 21 at 7:11












    • Oh yes, you're right, for xargs a newline is quoted with backslash only. I forgot about that, sorry.

      – Stéphane Chazelas
      Feb 21 at 7:15

















    • Note that $(<...) is a ksh operator, copied by zsh and bash (though bash still forks a process, so only save the cat execution there when using it). See Understanding Bash's Read-a-File Command Substitution for details.

      – Stéphane Chazelas
      Feb 21 at 6:33











    • @StéphaneChazelas included both suggestions.

      – mosvy
      Feb 21 at 6:45











    • @StéphaneChazelas no, it's not: printf '"anb" c' | xargs => xargs: unterminated quote, xargs: unmatched double quote, etc. Also the standard says: A string of zero or more non-double-quote ( '"') characters and non- <newline> characters can be quoted by enclosing them in double-quotes. Same thing for single quotes.

      – mosvy
      Feb 21 at 7:11












    • Oh yes, you're right, for xargs a newline is quoted with backslash only. I forgot about that, sorry.

      – Stéphane Chazelas
      Feb 21 at 7:15
















    Note that $(<...) is a ksh operator, copied by zsh and bash (though bash still forks a process, so only save the cat execution there when using it). See Understanding Bash's Read-a-File Command Substitution for details.

    – Stéphane Chazelas
    Feb 21 at 6:33





    Note that $(<...) is a ksh operator, copied by zsh and bash (though bash still forks a process, so only save the cat execution there when using it). See Understanding Bash's Read-a-File Command Substitution for details.

    – Stéphane Chazelas
    Feb 21 at 6:33













    @StéphaneChazelas included both suggestions.

    – mosvy
    Feb 21 at 6:45





    @StéphaneChazelas included both suggestions.

    – mosvy
    Feb 21 at 6:45













    @StéphaneChazelas no, it's not: printf '"anb" c' | xargs => xargs: unterminated quote, xargs: unmatched double quote, etc. Also the standard says: A string of zero or more non-double-quote ( '"') characters and non- <newline> characters can be quoted by enclosing them in double-quotes. Same thing for single quotes.

    – mosvy
    Feb 21 at 7:11






    @StéphaneChazelas no, it's not: printf '"anb" c' | xargs => xargs: unterminated quote, xargs: unmatched double quote, etc. Also the standard says: A string of zero or more non-double-quote ( '"') characters and non- <newline> characters can be quoted by enclosing them in double-quotes. Same thing for single quotes.

    – mosvy
    Feb 21 at 7:11














    Oh yes, you're right, for xargs a newline is quoted with backslash only. I forgot about that, sorry.

    – Stéphane Chazelas
    Feb 21 at 7:15





    Oh yes, you're right, for xargs a newline is quoted with backslash only. I forgot about that, sorry.

    – Stéphane Chazelas
    Feb 21 at 7:15













    1














    If instead of bash you're using ksh93 (ksh93 is the shell bash tries to mimic anyway), you could use the -S option of its read builtin which is to read csv (so understands csv-style quoting):



    IFS=" " read -rSA array < a.txt
    printf 'a: %sn' "$array[@]"


    With zsh, you could use it's z parameter expansion flag which is used to tokenise the content of a variable as if it was zsh code (and so understand quoting as zsh would, but not do the code evaluation that eval would do) along with the Q parameter expansion flag to remove one layer of quoting:



    IFS= read -r line < a.txt
    printf 'a: %sn' "$(Q@)$(z)line"


    (the @ parameter expansion flag is to preserve empty elements, reminiscent of ksh's $array[@] behaviour).



    If a.txt contains more than one line, with zsh you can replace the read command with content=$(<a.txt) and with ksh93 use read in a while loop (each read invocation potentially reading more than one line if a quoted string spans several line).






    share|improve this answer





























      1














      If instead of bash you're using ksh93 (ksh93 is the shell bash tries to mimic anyway), you could use the -S option of its read builtin which is to read csv (so understands csv-style quoting):



      IFS=" " read -rSA array < a.txt
      printf 'a: %sn' "$array[@]"


      With zsh, you could use it's z parameter expansion flag which is used to tokenise the content of a variable as if it was zsh code (and so understand quoting as zsh would, but not do the code evaluation that eval would do) along with the Q parameter expansion flag to remove one layer of quoting:



      IFS= read -r line < a.txt
      printf 'a: %sn' "$(Q@)$(z)line"


      (the @ parameter expansion flag is to preserve empty elements, reminiscent of ksh's $array[@] behaviour).



      If a.txt contains more than one line, with zsh you can replace the read command with content=$(<a.txt) and with ksh93 use read in a while loop (each read invocation potentially reading more than one line if a quoted string spans several line).






      share|improve this answer



























        1












        1








        1







        If instead of bash you're using ksh93 (ksh93 is the shell bash tries to mimic anyway), you could use the -S option of its read builtin which is to read csv (so understands csv-style quoting):



        IFS=" " read -rSA array < a.txt
        printf 'a: %sn' "$array[@]"


        With zsh, you could use it's z parameter expansion flag which is used to tokenise the content of a variable as if it was zsh code (and so understand quoting as zsh would, but not do the code evaluation that eval would do) along with the Q parameter expansion flag to remove one layer of quoting:



        IFS= read -r line < a.txt
        printf 'a: %sn' "$(Q@)$(z)line"


        (the @ parameter expansion flag is to preserve empty elements, reminiscent of ksh's $array[@] behaviour).



        If a.txt contains more than one line, with zsh you can replace the read command with content=$(<a.txt) and with ksh93 use read in a while loop (each read invocation potentially reading more than one line if a quoted string spans several line).






        share|improve this answer















        If instead of bash you're using ksh93 (ksh93 is the shell bash tries to mimic anyway), you could use the -S option of its read builtin which is to read csv (so understands csv-style quoting):



        IFS=" " read -rSA array < a.txt
        printf 'a: %sn' "$array[@]"


        With zsh, you could use it's z parameter expansion flag which is used to tokenise the content of a variable as if it was zsh code (and so understand quoting as zsh would, but not do the code evaluation that eval would do) along with the Q parameter expansion flag to remove one layer of quoting:



        IFS= read -r line < a.txt
        printf 'a: %sn' "$(Q@)$(z)line"


        (the @ parameter expansion flag is to preserve empty elements, reminiscent of ksh's $array[@] behaviour).



        If a.txt contains more than one line, with zsh you can replace the read command with content=$(<a.txt) and with ksh93 use read in a while loop (each read invocation potentially reading more than one line if a quoted string spans several line).







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Feb 21 at 7:08

























        answered Feb 21 at 6:27









        Stéphane ChazelasStéphane Chazelas

        310k57584945




        310k57584945



























            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%2f501994%2fread-from-file-then-use-for-to-split-fields-but-honor-quotes%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

            How to check contact read email or not when send email to Individual?

            Displaying single band from multi-band raster using QGIS

            How many registers does an x86_64 CPU actually have?