Awk command inside a for loop












2















I try, with no success, to use an awk command inside a for loop.



I've got a variable which contains a series of strings that I want to cut with awk to get the data.



I know how to do that but what I really want is to cut the data successively.



So I've got this variable:



var="data1,data2,data3"


And here where I am right now:



for ((i=1; i<=3; i++))
do
echo $(awk -F, '{print $1}' <<< $var)
done


I try to replace the $1 by the loop $i but without success.










share|improve this question

























  • Every character in between a pair of single quotes is treated as a literal character.

    – Niko Gambt
    Jan 27 at 11:50






  • 1





    What is your real use-case? looping over awk seems unnecessary here (for exaple in bash you could use a parameter substitution echo "${var//,/$'n'}")

    – steeldriver
    Jan 27 at 12:04











  • Actually the variable will contains urls from a zenity form. I want to use these urls separately so I have to get each one of them independently.

    – Amargein
    Jan 27 at 19:05











  • Relevant, but not a good solution in this case: How to assign value at run time in AWK command

    – Kusalananda
    Jan 27 at 22:54
















2















I try, with no success, to use an awk command inside a for loop.



I've got a variable which contains a series of strings that I want to cut with awk to get the data.



I know how to do that but what I really want is to cut the data successively.



So I've got this variable:



var="data1,data2,data3"


And here where I am right now:



for ((i=1; i<=3; i++))
do
echo $(awk -F, '{print $1}' <<< $var)
done


I try to replace the $1 by the loop $i but without success.










share|improve this question

























  • Every character in between a pair of single quotes is treated as a literal character.

    – Niko Gambt
    Jan 27 at 11:50






  • 1





    What is your real use-case? looping over awk seems unnecessary here (for exaple in bash you could use a parameter substitution echo "${var//,/$'n'}")

    – steeldriver
    Jan 27 at 12:04











  • Actually the variable will contains urls from a zenity form. I want to use these urls separately so I have to get each one of them independently.

    – Amargein
    Jan 27 at 19:05











  • Relevant, but not a good solution in this case: How to assign value at run time in AWK command

    – Kusalananda
    Jan 27 at 22:54














2












2








2








I try, with no success, to use an awk command inside a for loop.



I've got a variable which contains a series of strings that I want to cut with awk to get the data.



I know how to do that but what I really want is to cut the data successively.



So I've got this variable:



var="data1,data2,data3"


And here where I am right now:



for ((i=1; i<=3; i++))
do
echo $(awk -F, '{print $1}' <<< $var)
done


I try to replace the $1 by the loop $i but without success.










share|improve this question
















I try, with no success, to use an awk command inside a for loop.



I've got a variable which contains a series of strings that I want to cut with awk to get the data.



I know how to do that but what I really want is to cut the data successively.



So I've got this variable:



var="data1,data2,data3"


And here where I am right now:



for ((i=1; i<=3; i++))
do
echo $(awk -F, '{print $1}' <<< $var)
done


I try to replace the $1 by the loop $i but without success.







shell-script awk for






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 27 at 12:20









ilkkachu

59.1k892167




59.1k892167










asked Jan 27 at 11:37









AmargeinAmargein

163




163













  • Every character in between a pair of single quotes is treated as a literal character.

    – Niko Gambt
    Jan 27 at 11:50






  • 1





    What is your real use-case? looping over awk seems unnecessary here (for exaple in bash you could use a parameter substitution echo "${var//,/$'n'}")

    – steeldriver
    Jan 27 at 12:04











  • Actually the variable will contains urls from a zenity form. I want to use these urls separately so I have to get each one of them independently.

    – Amargein
    Jan 27 at 19:05











  • Relevant, but not a good solution in this case: How to assign value at run time in AWK command

    – Kusalananda
    Jan 27 at 22:54



















  • Every character in between a pair of single quotes is treated as a literal character.

    – Niko Gambt
    Jan 27 at 11:50






  • 1





    What is your real use-case? looping over awk seems unnecessary here (for exaple in bash you could use a parameter substitution echo "${var//,/$'n'}")

    – steeldriver
    Jan 27 at 12:04











  • Actually the variable will contains urls from a zenity form. I want to use these urls separately so I have to get each one of them independently.

    – Amargein
    Jan 27 at 19:05











  • Relevant, but not a good solution in this case: How to assign value at run time in AWK command

    – Kusalananda
    Jan 27 at 22:54

















Every character in between a pair of single quotes is treated as a literal character.

– Niko Gambt
Jan 27 at 11:50





Every character in between a pair of single quotes is treated as a literal character.

– Niko Gambt
Jan 27 at 11:50




1




1





What is your real use-case? looping over awk seems unnecessary here (for exaple in bash you could use a parameter substitution echo "${var//,/$'n'}")

– steeldriver
Jan 27 at 12:04





What is your real use-case? looping over awk seems unnecessary here (for exaple in bash you could use a parameter substitution echo "${var//,/$'n'}")

– steeldriver
Jan 27 at 12:04













Actually the variable will contains urls from a zenity form. I want to use these urls separately so I have to get each one of them independently.

– Amargein
Jan 27 at 19:05





Actually the variable will contains urls from a zenity form. I want to use these urls separately so I have to get each one of them independently.

– Amargein
Jan 27 at 19:05













Relevant, but not a good solution in this case: How to assign value at run time in AWK command

– Kusalananda
Jan 27 at 22:54





Relevant, but not a good solution in this case: How to assign value at run time in AWK command

– Kusalananda
Jan 27 at 22:54










4 Answers
4






active

oldest

votes


















4














You can accomplish what you're trying to do by using double quotes in the awk script to inject the shell variable into it. You still want to keep one literal $ in it, which you can do by escaping it with backslash:



echo $(awk -F, "{print $$i}" <<<$var)


This will expand the $i to 1, 2 and 3 in each of the iterations, therefore awk will see $1, $2 and $3 which will make it expand each of the fields.



Another possibility is to inject the shell variable as an awk variable using the -v flag:



echo $(awk -F, -v i="$i" '{print $i}' <<<$var)


That assigns the awk variable i to the contents of the shell variable with the same name. Variables in awk don't use a $, which is used for fields, so $i is enough to refer to the i-th field if i is a variable in awk.



Assigning an awk variable with -v is generally a safer approach, particularly when it can contain arbitrary sequences of characters, in that case there's less risk that the contents will be executed as awk code against your intentions. But since in your case the variable holds a single integer, that's less of a concern.



Yet another option is to use a for loop in awk itself. See awk documentation (or search this site) for more details on how to do that.






share|improve this answer





















  • 1





    ... or set the input record separator appropriately awk -v RS='[,n]' 1 <<< "$var" (or maybe more portably printf "$var" | awk -v RS=, 1 )

    – steeldriver
    Jan 27 at 12:06











  • @steeldriver That awk script will print all three fields at once. Which is ok given the OP is doing just that... I ended up focusing the answer on extracting a single field on the assumption they were interested in executing other commands in the shell loop (which might have been the motivation for using one in the first place...)

    – filbranden
    Jan 27 at 12:13






  • 1





    Understood - that's why I commented on the OP to clarify what they really want to do ;)

    – steeldriver
    Jan 27 at 12:15






  • 1





    The first is an injection (and a security concern), the second one (using -v) is not an injection.

    – Kusalananda
    Jan 27 at 12:41






  • 1





    Thanks, your answer solved my problem! First time I post a question here after years of reading posts. Not disappointed. Such a great community!

    – Amargein
    Jan 27 at 19:06



















1














Using awk seems excessive in this circumstance, how about a tr and a while-loop:



tr , 'n' <<<"$var" | while read; do
echo $REPLY
done


Output:



data1
data2
data3





share|improve this answer
























  • Great. REPLY being the default name argument for read built-in shell command.

    – w17t
    Jan 27 at 12:21






  • 2





    Note that this requires that the shell uses a default variable to put the data in from read, which bash happens to do, but this is not standard. Also, your read command may modify the data if it contains backslashes, and may strip flanking whitespace from the values. It would also read values with embedded newlines as multiple values. You additionally need "$REPLY" to stop the shell from splitting the value and from performing filename expansion on it.

    – Kusalananda
    Jan 27 at 12:40



















1














awk can accept both j (as variable) and $j (as field index):



for i in 1 2 3; do echo "$var" | awk -v j=$i -F , '{print $j}'; done


$i in the example "confused" awk which one to use (shell or its own variable - taking precedence) as both are referred to with $ prefix.



note



sh shell which is standard for "portable" scripting do not support:



(( i=1; i<=3; i++; )) and <<< $var constructs



Also you might consider using seq command in for loop for finer control in number sequence generation, if available.






share|improve this answer





















  • 3





    Your loop would only work if you happened to have three files called 1, 2 and 3 in the current directory. Also, you use variable expansion unquoted in the shell which may have unwanted consequences if the data contains filename patterns (like *). The echo may furthermore modify the data if it contains backslashes.

    – Kusalananda
    Jan 27 at 13:22











  • Thanks, corrected.

    – w17t
    Jan 27 at 13:39



















0














#!/bin/sh

var='data1,data2,data3'

unset data
while [ "$var" != "$data" ]; do
data=${var%%,*} # delete first comma and the bit after it
var=${var#*,} # delete bit up to first comma (and the comma)

printf 'data = "%s"n' "$data"
done


Here, we use variable substitutions to get each successive comma-delimited data field from the value of the var variable. The first assignment to data in the loop will remove everything from $var after the first comma. The var variable is then modified so that the first bit up to the first comma is deleted.



This continues until "$var" = "$data" which means that nothing more can be done to the string.



This way of doing it would allow us to handle comma-separated data strings that contain embedded newlines:



var='line1
line2,data2,last bit
goes here'


With the above values in var, the above script would output



data = "line1
line2"
data = "data2"
data = "last bit
goes here"




Not caring about embedded newlines; You very seldom have to loop over invocations of awk.



Note that awk is perfectly happy to read your string as a set of comma-delimited fields, and that it's able to loop over these:



printf '%sn' "$var" |
awk -F ',' '{ for (i=1; i<=NF; i++) print $i }'


With var='data1,data2,data3', this would print



data1
data2
data3




Another shell solution that makes use of the IFS variable to split the $var value into bits while also using set -f to disable filename expansion:



set -f
oldIFS=$IFS; IFS=','

set -- $var

IFS=$oldIFS; unset oldIFS
set +f

for data do
printf 'data = "%s"n' "$data"
done





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%2f496994%2fawk-command-inside-a-for-loop%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    4














    You can accomplish what you're trying to do by using double quotes in the awk script to inject the shell variable into it. You still want to keep one literal $ in it, which you can do by escaping it with backslash:



    echo $(awk -F, "{print $$i}" <<<$var)


    This will expand the $i to 1, 2 and 3 in each of the iterations, therefore awk will see $1, $2 and $3 which will make it expand each of the fields.



    Another possibility is to inject the shell variable as an awk variable using the -v flag:



    echo $(awk -F, -v i="$i" '{print $i}' <<<$var)


    That assigns the awk variable i to the contents of the shell variable with the same name. Variables in awk don't use a $, which is used for fields, so $i is enough to refer to the i-th field if i is a variable in awk.



    Assigning an awk variable with -v is generally a safer approach, particularly when it can contain arbitrary sequences of characters, in that case there's less risk that the contents will be executed as awk code against your intentions. But since in your case the variable holds a single integer, that's less of a concern.



    Yet another option is to use a for loop in awk itself. See awk documentation (or search this site) for more details on how to do that.






    share|improve this answer





















    • 1





      ... or set the input record separator appropriately awk -v RS='[,n]' 1 <<< "$var" (or maybe more portably printf "$var" | awk -v RS=, 1 )

      – steeldriver
      Jan 27 at 12:06











    • @steeldriver That awk script will print all three fields at once. Which is ok given the OP is doing just that... I ended up focusing the answer on extracting a single field on the assumption they were interested in executing other commands in the shell loop (which might have been the motivation for using one in the first place...)

      – filbranden
      Jan 27 at 12:13






    • 1





      Understood - that's why I commented on the OP to clarify what they really want to do ;)

      – steeldriver
      Jan 27 at 12:15






    • 1





      The first is an injection (and a security concern), the second one (using -v) is not an injection.

      – Kusalananda
      Jan 27 at 12:41






    • 1





      Thanks, your answer solved my problem! First time I post a question here after years of reading posts. Not disappointed. Such a great community!

      – Amargein
      Jan 27 at 19:06
















    4














    You can accomplish what you're trying to do by using double quotes in the awk script to inject the shell variable into it. You still want to keep one literal $ in it, which you can do by escaping it with backslash:



    echo $(awk -F, "{print $$i}" <<<$var)


    This will expand the $i to 1, 2 and 3 in each of the iterations, therefore awk will see $1, $2 and $3 which will make it expand each of the fields.



    Another possibility is to inject the shell variable as an awk variable using the -v flag:



    echo $(awk -F, -v i="$i" '{print $i}' <<<$var)


    That assigns the awk variable i to the contents of the shell variable with the same name. Variables in awk don't use a $, which is used for fields, so $i is enough to refer to the i-th field if i is a variable in awk.



    Assigning an awk variable with -v is generally a safer approach, particularly when it can contain arbitrary sequences of characters, in that case there's less risk that the contents will be executed as awk code against your intentions. But since in your case the variable holds a single integer, that's less of a concern.



    Yet another option is to use a for loop in awk itself. See awk documentation (or search this site) for more details on how to do that.






    share|improve this answer





















    • 1





      ... or set the input record separator appropriately awk -v RS='[,n]' 1 <<< "$var" (or maybe more portably printf "$var" | awk -v RS=, 1 )

      – steeldriver
      Jan 27 at 12:06











    • @steeldriver That awk script will print all three fields at once. Which is ok given the OP is doing just that... I ended up focusing the answer on extracting a single field on the assumption they were interested in executing other commands in the shell loop (which might have been the motivation for using one in the first place...)

      – filbranden
      Jan 27 at 12:13






    • 1





      Understood - that's why I commented on the OP to clarify what they really want to do ;)

      – steeldriver
      Jan 27 at 12:15






    • 1





      The first is an injection (and a security concern), the second one (using -v) is not an injection.

      – Kusalananda
      Jan 27 at 12:41






    • 1





      Thanks, your answer solved my problem! First time I post a question here after years of reading posts. Not disappointed. Such a great community!

      – Amargein
      Jan 27 at 19:06














    4












    4








    4







    You can accomplish what you're trying to do by using double quotes in the awk script to inject the shell variable into it. You still want to keep one literal $ in it, which you can do by escaping it with backslash:



    echo $(awk -F, "{print $$i}" <<<$var)


    This will expand the $i to 1, 2 and 3 in each of the iterations, therefore awk will see $1, $2 and $3 which will make it expand each of the fields.



    Another possibility is to inject the shell variable as an awk variable using the -v flag:



    echo $(awk -F, -v i="$i" '{print $i}' <<<$var)


    That assigns the awk variable i to the contents of the shell variable with the same name. Variables in awk don't use a $, which is used for fields, so $i is enough to refer to the i-th field if i is a variable in awk.



    Assigning an awk variable with -v is generally a safer approach, particularly when it can contain arbitrary sequences of characters, in that case there's less risk that the contents will be executed as awk code against your intentions. But since in your case the variable holds a single integer, that's less of a concern.



    Yet another option is to use a for loop in awk itself. See awk documentation (or search this site) for more details on how to do that.






    share|improve this answer















    You can accomplish what you're trying to do by using double quotes in the awk script to inject the shell variable into it. You still want to keep one literal $ in it, which you can do by escaping it with backslash:



    echo $(awk -F, "{print $$i}" <<<$var)


    This will expand the $i to 1, 2 and 3 in each of the iterations, therefore awk will see $1, $2 and $3 which will make it expand each of the fields.



    Another possibility is to inject the shell variable as an awk variable using the -v flag:



    echo $(awk -F, -v i="$i" '{print $i}' <<<$var)


    That assigns the awk variable i to the contents of the shell variable with the same name. Variables in awk don't use a $, which is used for fields, so $i is enough to refer to the i-th field if i is a variable in awk.



    Assigning an awk variable with -v is generally a safer approach, particularly when it can contain arbitrary sequences of characters, in that case there's less risk that the contents will be executed as awk code against your intentions. But since in your case the variable holds a single integer, that's less of a concern.



    Yet another option is to use a for loop in awk itself. See awk documentation (or search this site) for more details on how to do that.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 27 at 12:45

























    answered Jan 27 at 11:46









    filbrandenfilbranden

    8,30621140




    8,30621140








    • 1





      ... or set the input record separator appropriately awk -v RS='[,n]' 1 <<< "$var" (or maybe more portably printf "$var" | awk -v RS=, 1 )

      – steeldriver
      Jan 27 at 12:06











    • @steeldriver That awk script will print all three fields at once. Which is ok given the OP is doing just that... I ended up focusing the answer on extracting a single field on the assumption they were interested in executing other commands in the shell loop (which might have been the motivation for using one in the first place...)

      – filbranden
      Jan 27 at 12:13






    • 1





      Understood - that's why I commented on the OP to clarify what they really want to do ;)

      – steeldriver
      Jan 27 at 12:15






    • 1





      The first is an injection (and a security concern), the second one (using -v) is not an injection.

      – Kusalananda
      Jan 27 at 12:41






    • 1





      Thanks, your answer solved my problem! First time I post a question here after years of reading posts. Not disappointed. Such a great community!

      – Amargein
      Jan 27 at 19:06














    • 1





      ... or set the input record separator appropriately awk -v RS='[,n]' 1 <<< "$var" (or maybe more portably printf "$var" | awk -v RS=, 1 )

      – steeldriver
      Jan 27 at 12:06











    • @steeldriver That awk script will print all three fields at once. Which is ok given the OP is doing just that... I ended up focusing the answer on extracting a single field on the assumption they were interested in executing other commands in the shell loop (which might have been the motivation for using one in the first place...)

      – filbranden
      Jan 27 at 12:13






    • 1





      Understood - that's why I commented on the OP to clarify what they really want to do ;)

      – steeldriver
      Jan 27 at 12:15






    • 1





      The first is an injection (and a security concern), the second one (using -v) is not an injection.

      – Kusalananda
      Jan 27 at 12:41






    • 1





      Thanks, your answer solved my problem! First time I post a question here after years of reading posts. Not disappointed. Such a great community!

      – Amargein
      Jan 27 at 19:06








    1




    1





    ... or set the input record separator appropriately awk -v RS='[,n]' 1 <<< "$var" (or maybe more portably printf "$var" | awk -v RS=, 1 )

    – steeldriver
    Jan 27 at 12:06





    ... or set the input record separator appropriately awk -v RS='[,n]' 1 <<< "$var" (or maybe more portably printf "$var" | awk -v RS=, 1 )

    – steeldriver
    Jan 27 at 12:06













    @steeldriver That awk script will print all three fields at once. Which is ok given the OP is doing just that... I ended up focusing the answer on extracting a single field on the assumption they were interested in executing other commands in the shell loop (which might have been the motivation for using one in the first place...)

    – filbranden
    Jan 27 at 12:13





    @steeldriver That awk script will print all three fields at once. Which is ok given the OP is doing just that... I ended up focusing the answer on extracting a single field on the assumption they were interested in executing other commands in the shell loop (which might have been the motivation for using one in the first place...)

    – filbranden
    Jan 27 at 12:13




    1




    1





    Understood - that's why I commented on the OP to clarify what they really want to do ;)

    – steeldriver
    Jan 27 at 12:15





    Understood - that's why I commented on the OP to clarify what they really want to do ;)

    – steeldriver
    Jan 27 at 12:15




    1




    1





    The first is an injection (and a security concern), the second one (using -v) is not an injection.

    – Kusalananda
    Jan 27 at 12:41





    The first is an injection (and a security concern), the second one (using -v) is not an injection.

    – Kusalananda
    Jan 27 at 12:41




    1




    1





    Thanks, your answer solved my problem! First time I post a question here after years of reading posts. Not disappointed. Such a great community!

    – Amargein
    Jan 27 at 19:06





    Thanks, your answer solved my problem! First time I post a question here after years of reading posts. Not disappointed. Such a great community!

    – Amargein
    Jan 27 at 19:06













    1














    Using awk seems excessive in this circumstance, how about a tr and a while-loop:



    tr , 'n' <<<"$var" | while read; do
    echo $REPLY
    done


    Output:



    data1
    data2
    data3





    share|improve this answer
























    • Great. REPLY being the default name argument for read built-in shell command.

      – w17t
      Jan 27 at 12:21






    • 2





      Note that this requires that the shell uses a default variable to put the data in from read, which bash happens to do, but this is not standard. Also, your read command may modify the data if it contains backslashes, and may strip flanking whitespace from the values. It would also read values with embedded newlines as multiple values. You additionally need "$REPLY" to stop the shell from splitting the value and from performing filename expansion on it.

      – Kusalananda
      Jan 27 at 12:40
















    1














    Using awk seems excessive in this circumstance, how about a tr and a while-loop:



    tr , 'n' <<<"$var" | while read; do
    echo $REPLY
    done


    Output:



    data1
    data2
    data3





    share|improve this answer
























    • Great. REPLY being the default name argument for read built-in shell command.

      – w17t
      Jan 27 at 12:21






    • 2





      Note that this requires that the shell uses a default variable to put the data in from read, which bash happens to do, but this is not standard. Also, your read command may modify the data if it contains backslashes, and may strip flanking whitespace from the values. It would also read values with embedded newlines as multiple values. You additionally need "$REPLY" to stop the shell from splitting the value and from performing filename expansion on it.

      – Kusalananda
      Jan 27 at 12:40














    1












    1








    1







    Using awk seems excessive in this circumstance, how about a tr and a while-loop:



    tr , 'n' <<<"$var" | while read; do
    echo $REPLY
    done


    Output:



    data1
    data2
    data3





    share|improve this answer













    Using awk seems excessive in this circumstance, how about a tr and a while-loop:



    tr , 'n' <<<"$var" | while read; do
    echo $REPLY
    done


    Output:



    data1
    data2
    data3






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 27 at 12:15









    ThorThor

    11.8k13459




    11.8k13459













    • Great. REPLY being the default name argument for read built-in shell command.

      – w17t
      Jan 27 at 12:21






    • 2





      Note that this requires that the shell uses a default variable to put the data in from read, which bash happens to do, but this is not standard. Also, your read command may modify the data if it contains backslashes, and may strip flanking whitespace from the values. It would also read values with embedded newlines as multiple values. You additionally need "$REPLY" to stop the shell from splitting the value and from performing filename expansion on it.

      – Kusalananda
      Jan 27 at 12:40



















    • Great. REPLY being the default name argument for read built-in shell command.

      – w17t
      Jan 27 at 12:21






    • 2





      Note that this requires that the shell uses a default variable to put the data in from read, which bash happens to do, but this is not standard. Also, your read command may modify the data if it contains backslashes, and may strip flanking whitespace from the values. It would also read values with embedded newlines as multiple values. You additionally need "$REPLY" to stop the shell from splitting the value and from performing filename expansion on it.

      – Kusalananda
      Jan 27 at 12:40

















    Great. REPLY being the default name argument for read built-in shell command.

    – w17t
    Jan 27 at 12:21





    Great. REPLY being the default name argument for read built-in shell command.

    – w17t
    Jan 27 at 12:21




    2




    2





    Note that this requires that the shell uses a default variable to put the data in from read, which bash happens to do, but this is not standard. Also, your read command may modify the data if it contains backslashes, and may strip flanking whitespace from the values. It would also read values with embedded newlines as multiple values. You additionally need "$REPLY" to stop the shell from splitting the value and from performing filename expansion on it.

    – Kusalananda
    Jan 27 at 12:40





    Note that this requires that the shell uses a default variable to put the data in from read, which bash happens to do, but this is not standard. Also, your read command may modify the data if it contains backslashes, and may strip flanking whitespace from the values. It would also read values with embedded newlines as multiple values. You additionally need "$REPLY" to stop the shell from splitting the value and from performing filename expansion on it.

    – Kusalananda
    Jan 27 at 12:40











    1














    awk can accept both j (as variable) and $j (as field index):



    for i in 1 2 3; do echo "$var" | awk -v j=$i -F , '{print $j}'; done


    $i in the example "confused" awk which one to use (shell or its own variable - taking precedence) as both are referred to with $ prefix.



    note



    sh shell which is standard for "portable" scripting do not support:



    (( i=1; i<=3; i++; )) and <<< $var constructs



    Also you might consider using seq command in for loop for finer control in number sequence generation, if available.






    share|improve this answer





















    • 3





      Your loop would only work if you happened to have three files called 1, 2 and 3 in the current directory. Also, you use variable expansion unquoted in the shell which may have unwanted consequences if the data contains filename patterns (like *). The echo may furthermore modify the data if it contains backslashes.

      – Kusalananda
      Jan 27 at 13:22











    • Thanks, corrected.

      – w17t
      Jan 27 at 13:39
















    1














    awk can accept both j (as variable) and $j (as field index):



    for i in 1 2 3; do echo "$var" | awk -v j=$i -F , '{print $j}'; done


    $i in the example "confused" awk which one to use (shell or its own variable - taking precedence) as both are referred to with $ prefix.



    note



    sh shell which is standard for "portable" scripting do not support:



    (( i=1; i<=3; i++; )) and <<< $var constructs



    Also you might consider using seq command in for loop for finer control in number sequence generation, if available.






    share|improve this answer





















    • 3





      Your loop would only work if you happened to have three files called 1, 2 and 3 in the current directory. Also, you use variable expansion unquoted in the shell which may have unwanted consequences if the data contains filename patterns (like *). The echo may furthermore modify the data if it contains backslashes.

      – Kusalananda
      Jan 27 at 13:22











    • Thanks, corrected.

      – w17t
      Jan 27 at 13:39














    1












    1








    1







    awk can accept both j (as variable) and $j (as field index):



    for i in 1 2 3; do echo "$var" | awk -v j=$i -F , '{print $j}'; done


    $i in the example "confused" awk which one to use (shell or its own variable - taking precedence) as both are referred to with $ prefix.



    note



    sh shell which is standard for "portable" scripting do not support:



    (( i=1; i<=3; i++; )) and <<< $var constructs



    Also you might consider using seq command in for loop for finer control in number sequence generation, if available.






    share|improve this answer















    awk can accept both j (as variable) and $j (as field index):



    for i in 1 2 3; do echo "$var" | awk -v j=$i -F , '{print $j}'; done


    $i in the example "confused" awk which one to use (shell or its own variable - taking precedence) as both are referred to with $ prefix.



    note



    sh shell which is standard for "portable" scripting do not support:



    (( i=1; i<=3; i++; )) and <<< $var constructs



    Also you might consider using seq command in for loop for finer control in number sequence generation, if available.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 27 at 13:38

























    answered Jan 27 at 12:06









    w17tw17t

    695524




    695524








    • 3





      Your loop would only work if you happened to have three files called 1, 2 and 3 in the current directory. Also, you use variable expansion unquoted in the shell which may have unwanted consequences if the data contains filename patterns (like *). The echo may furthermore modify the data if it contains backslashes.

      – Kusalananda
      Jan 27 at 13:22











    • Thanks, corrected.

      – w17t
      Jan 27 at 13:39














    • 3





      Your loop would only work if you happened to have three files called 1, 2 and 3 in the current directory. Also, you use variable expansion unquoted in the shell which may have unwanted consequences if the data contains filename patterns (like *). The echo may furthermore modify the data if it contains backslashes.

      – Kusalananda
      Jan 27 at 13:22











    • Thanks, corrected.

      – w17t
      Jan 27 at 13:39








    3




    3





    Your loop would only work if you happened to have three files called 1, 2 and 3 in the current directory. Also, you use variable expansion unquoted in the shell which may have unwanted consequences if the data contains filename patterns (like *). The echo may furthermore modify the data if it contains backslashes.

    – Kusalananda
    Jan 27 at 13:22





    Your loop would only work if you happened to have three files called 1, 2 and 3 in the current directory. Also, you use variable expansion unquoted in the shell which may have unwanted consequences if the data contains filename patterns (like *). The echo may furthermore modify the data if it contains backslashes.

    – Kusalananda
    Jan 27 at 13:22













    Thanks, corrected.

    – w17t
    Jan 27 at 13:39





    Thanks, corrected.

    – w17t
    Jan 27 at 13:39











    0














    #!/bin/sh

    var='data1,data2,data3'

    unset data
    while [ "$var" != "$data" ]; do
    data=${var%%,*} # delete first comma and the bit after it
    var=${var#*,} # delete bit up to first comma (and the comma)

    printf 'data = "%s"n' "$data"
    done


    Here, we use variable substitutions to get each successive comma-delimited data field from the value of the var variable. The first assignment to data in the loop will remove everything from $var after the first comma. The var variable is then modified so that the first bit up to the first comma is deleted.



    This continues until "$var" = "$data" which means that nothing more can be done to the string.



    This way of doing it would allow us to handle comma-separated data strings that contain embedded newlines:



    var='line1
    line2,data2,last bit
    goes here'


    With the above values in var, the above script would output



    data = "line1
    line2"
    data = "data2"
    data = "last bit
    goes here"




    Not caring about embedded newlines; You very seldom have to loop over invocations of awk.



    Note that awk is perfectly happy to read your string as a set of comma-delimited fields, and that it's able to loop over these:



    printf '%sn' "$var" |
    awk -F ',' '{ for (i=1; i<=NF; i++) print $i }'


    With var='data1,data2,data3', this would print



    data1
    data2
    data3




    Another shell solution that makes use of the IFS variable to split the $var value into bits while also using set -f to disable filename expansion:



    set -f
    oldIFS=$IFS; IFS=','

    set -- $var

    IFS=$oldIFS; unset oldIFS
    set +f

    for data do
    printf 'data = "%s"n' "$data"
    done





    share|improve this answer






























      0














      #!/bin/sh

      var='data1,data2,data3'

      unset data
      while [ "$var" != "$data" ]; do
      data=${var%%,*} # delete first comma and the bit after it
      var=${var#*,} # delete bit up to first comma (and the comma)

      printf 'data = "%s"n' "$data"
      done


      Here, we use variable substitutions to get each successive comma-delimited data field from the value of the var variable. The first assignment to data in the loop will remove everything from $var after the first comma. The var variable is then modified so that the first bit up to the first comma is deleted.



      This continues until "$var" = "$data" which means that nothing more can be done to the string.



      This way of doing it would allow us to handle comma-separated data strings that contain embedded newlines:



      var='line1
      line2,data2,last bit
      goes here'


      With the above values in var, the above script would output



      data = "line1
      line2"
      data = "data2"
      data = "last bit
      goes here"




      Not caring about embedded newlines; You very seldom have to loop over invocations of awk.



      Note that awk is perfectly happy to read your string as a set of comma-delimited fields, and that it's able to loop over these:



      printf '%sn' "$var" |
      awk -F ',' '{ for (i=1; i<=NF; i++) print $i }'


      With var='data1,data2,data3', this would print



      data1
      data2
      data3




      Another shell solution that makes use of the IFS variable to split the $var value into bits while also using set -f to disable filename expansion:



      set -f
      oldIFS=$IFS; IFS=','

      set -- $var

      IFS=$oldIFS; unset oldIFS
      set +f

      for data do
      printf 'data = "%s"n' "$data"
      done





      share|improve this answer




























        0












        0








        0







        #!/bin/sh

        var='data1,data2,data3'

        unset data
        while [ "$var" != "$data" ]; do
        data=${var%%,*} # delete first comma and the bit after it
        var=${var#*,} # delete bit up to first comma (and the comma)

        printf 'data = "%s"n' "$data"
        done


        Here, we use variable substitutions to get each successive comma-delimited data field from the value of the var variable. The first assignment to data in the loop will remove everything from $var after the first comma. The var variable is then modified so that the first bit up to the first comma is deleted.



        This continues until "$var" = "$data" which means that nothing more can be done to the string.



        This way of doing it would allow us to handle comma-separated data strings that contain embedded newlines:



        var='line1
        line2,data2,last bit
        goes here'


        With the above values in var, the above script would output



        data = "line1
        line2"
        data = "data2"
        data = "last bit
        goes here"




        Not caring about embedded newlines; You very seldom have to loop over invocations of awk.



        Note that awk is perfectly happy to read your string as a set of comma-delimited fields, and that it's able to loop over these:



        printf '%sn' "$var" |
        awk -F ',' '{ for (i=1; i<=NF; i++) print $i }'


        With var='data1,data2,data3', this would print



        data1
        data2
        data3




        Another shell solution that makes use of the IFS variable to split the $var value into bits while also using set -f to disable filename expansion:



        set -f
        oldIFS=$IFS; IFS=','

        set -- $var

        IFS=$oldIFS; unset oldIFS
        set +f

        for data do
        printf 'data = "%s"n' "$data"
        done





        share|improve this answer















        #!/bin/sh

        var='data1,data2,data3'

        unset data
        while [ "$var" != "$data" ]; do
        data=${var%%,*} # delete first comma and the bit after it
        var=${var#*,} # delete bit up to first comma (and the comma)

        printf 'data = "%s"n' "$data"
        done


        Here, we use variable substitutions to get each successive comma-delimited data field from the value of the var variable. The first assignment to data in the loop will remove everything from $var after the first comma. The var variable is then modified so that the first bit up to the first comma is deleted.



        This continues until "$var" = "$data" which means that nothing more can be done to the string.



        This way of doing it would allow us to handle comma-separated data strings that contain embedded newlines:



        var='line1
        line2,data2,last bit
        goes here'


        With the above values in var, the above script would output



        data = "line1
        line2"
        data = "data2"
        data = "last bit
        goes here"




        Not caring about embedded newlines; You very seldom have to loop over invocations of awk.



        Note that awk is perfectly happy to read your string as a set of comma-delimited fields, and that it's able to loop over these:



        printf '%sn' "$var" |
        awk -F ',' '{ for (i=1; i<=NF; i++) print $i }'


        With var='data1,data2,data3', this would print



        data1
        data2
        data3




        Another shell solution that makes use of the IFS variable to split the $var value into bits while also using set -f to disable filename expansion:



        set -f
        oldIFS=$IFS; IFS=','

        set -- $var

        IFS=$oldIFS; unset oldIFS
        set +f

        for data do
        printf 'data = "%s"n' "$data"
        done






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 27 at 13:38

























        answered Jan 27 at 12:51









        KusalanandaKusalananda

        131k17249408




        131k17249408






























            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%2f496994%2fawk-command-inside-a-for-loop%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 do I know what Microsoft account the skydrive app is syncing to?

            When does type information flow backwards in C++?

            Grease: Live!