while-loop and if-statement do different command if condition is met

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











up vote
2
down vote

favorite
1












Inside file.txt



chicken sheep cow 
tomato cucumber
banana


Without if statement



while read -r column1 column2 column3; do 
command
done < file.txt


Using if statement, how to if the line has three columns, it do command1, if it has two columns, do command2 and if only has one column, it do command3?







share|improve this question






















  • (What if there are more than three? That read would concatenate the fourth and so on with the third one.)
    – ilkkachu
    Oct 29 '17 at 22:50














up vote
2
down vote

favorite
1












Inside file.txt



chicken sheep cow 
tomato cucumber
banana


Without if statement



while read -r column1 column2 column3; do 
command
done < file.txt


Using if statement, how to if the line has three columns, it do command1, if it has two columns, do command2 and if only has one column, it do command3?







share|improve this question






















  • (What if there are more than three? That read would concatenate the fourth and so on with the third one.)
    – ilkkachu
    Oct 29 '17 at 22:50












up vote
2
down vote

favorite
1









up vote
2
down vote

favorite
1






1





Inside file.txt



chicken sheep cow 
tomato cucumber
banana


Without if statement



while read -r column1 column2 column3; do 
command
done < file.txt


Using if statement, how to if the line has three columns, it do command1, if it has two columns, do command2 and if only has one column, it do command3?







share|improve this question














Inside file.txt



chicken sheep cow 
tomato cucumber
banana


Without if statement



while read -r column1 column2 column3; do 
command
done < file.txt


Using if statement, how to if the line has three columns, it do command1, if it has two columns, do command2 and if only has one column, it do command3?









share|improve this question













share|improve this question




share|improve this question








edited Oct 29 '17 at 19:40

























asked Oct 29 '17 at 19:21









Hidayats

3017




3017











  • (What if there are more than three? That read would concatenate the fourth and so on with the third one.)
    – ilkkachu
    Oct 29 '17 at 22:50
















  • (What if there are more than three? That read would concatenate the fourth and so on with the third one.)
    – ilkkachu
    Oct 29 '17 at 22:50















(What if there are more than three? That read would concatenate the fourth and so on with the third one.)
– ilkkachu
Oct 29 '17 at 22:50




(What if there are more than three? That read would concatenate the fourth and so on with the third one.)
– ilkkachu
Oct 29 '17 at 22:50










4 Answers
4






active

oldest

votes

















up vote
3
down vote



accepted










Or other approach with smallest difference of your example:



#!/bin/bash

while read -r column1 column2 column3; do
if [ -z "$column2" ] ; then
printf '%sn' "Only first column has data"
elif [ -z "$column3" ]; then
printf '%sn' "Only first and second columns has data"
elif [ -n "$column3" ]; then
printf '%sn' "All three columns has data"
fi
done < file.txt


Output will be:



All three columns has data
Only first and second columns has data
Only first column has data


Notes:



In your example first and second lines contains several spaces at the end, but by default read removes all leading and trailing space characters.



If your input contains more than 3 columns, all data in third column and further will placed in column3



See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?






share|improve this answer






















  • You need to quote the variables in the tests: [ -n "$var" ] etc. With -z it works without the quotes here, slightly accidentally, since if $var is empty in [ -z $var ], the expansion is just [ -z ] which just tests if -z is a nonempty string. The one with -n, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
    – ilkkachu
    Oct 29 '17 at 22:48











  • @ilkkachu, thx. It's fair remark, answer was changed
    – Egor Vasilyev
    Oct 30 '17 at 5:22


















up vote
1
down vote













You may read each line into array with read -ra, then, check the array size:



fmt="Number of fields: %s. The last one: %sn"
while read -ra items; do
if [ $#items[*] == 3 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 2 ]; then
printf "$fmt" $#items[*] $items[-1]
elif [ $#items[*] == 1 ]; then
printf "$fmt" $#items[*] $items[-1]
fi
done < file.txt



Of course, expression printf "$fmt" $#items[*] $items[-1] was used just for demonstration, you can define your own.




The above approach outputs(as an example):



Number of fields: 3. The last one: cow
Number of fields: 2. The last one: cucumber
Number of fields: 1. The last one: banana





share|improve this answer





























    up vote
    1
    down vote













    while read -r column1 column2 column3; do
    if [ -z "$column2" ]; then
    # one column
    : command
    elif [ -z "$column3" ]; then
    # two columns
    : command
    else
    # three columns
    : command
    fi
    done < file.txt


    or



    while read -r column1 column2 column3; do
    set -- $column1 $column2 $column3
    case $# in
    1)
    : command
    ;;
    2)
    : command
    ;;
    *)
    : command
    ;;
    esac
    done < file.txt





    share|improve this answer



























      up vote
      0
      down vote













      Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash or ksh ( which also can be handy in case we do want to keep positional parameters). The below example is for bash ( note that for ksh or mksh you'd use -A insead of -a in read, and of course change #! line):



      #!/usr/bin/env bash
      line_counter=1
      while read -r -a arr;
      do
      case "$#arr[@]" in
      1) printf "One column in line %dn" "$line_counter";;
      2) printf "Two columns in line %dn" "$line_counter";;
      3) printf "Three columns in line %dn" "$line_counter";;
      *) printf "More than 3 lines in line %dn" "$line_counter";;
      esac
      ((line_counter++))
      done < input.txt


      And the output is like so:



      $ ./eval_columns.sh 
      Three columns in line 1
      Two columns in line 2
      One column in line 3





      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',
        convertImagesToLinks: false,
        noModals: false,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: null,
        bindNavPrevention: true,
        postfix: "",
        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%2f401270%2fwhile-loop-and-if-statement-do-different-command-if-condition-is-met%23new-answer', 'question_page');

        );

        Post as a guest






























        4 Answers
        4






        active

        oldest

        votes








        4 Answers
        4






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        3
        down vote



        accepted










        Or other approach with smallest difference of your example:



        #!/bin/bash

        while read -r column1 column2 column3; do
        if [ -z "$column2" ] ; then
        printf '%sn' "Only first column has data"
        elif [ -z "$column3" ]; then
        printf '%sn' "Only first and second columns has data"
        elif [ -n "$column3" ]; then
        printf '%sn' "All three columns has data"
        fi
        done < file.txt


        Output will be:



        All three columns has data
        Only first and second columns has data
        Only first column has data


        Notes:



        In your example first and second lines contains several spaces at the end, but by default read removes all leading and trailing space characters.



        If your input contains more than 3 columns, all data in third column and further will placed in column3



        See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?






        share|improve this answer






















        • You need to quote the variables in the tests: [ -n "$var" ] etc. With -z it works without the quotes here, slightly accidentally, since if $var is empty in [ -z $var ], the expansion is just [ -z ] which just tests if -z is a nonempty string. The one with -n, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
          – ilkkachu
          Oct 29 '17 at 22:48











        • @ilkkachu, thx. It's fair remark, answer was changed
          – Egor Vasilyev
          Oct 30 '17 at 5:22















        up vote
        3
        down vote



        accepted










        Or other approach with smallest difference of your example:



        #!/bin/bash

        while read -r column1 column2 column3; do
        if [ -z "$column2" ] ; then
        printf '%sn' "Only first column has data"
        elif [ -z "$column3" ]; then
        printf '%sn' "Only first and second columns has data"
        elif [ -n "$column3" ]; then
        printf '%sn' "All three columns has data"
        fi
        done < file.txt


        Output will be:



        All three columns has data
        Only first and second columns has data
        Only first column has data


        Notes:



        In your example first and second lines contains several spaces at the end, but by default read removes all leading and trailing space characters.



        If your input contains more than 3 columns, all data in third column and further will placed in column3



        See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?






        share|improve this answer






















        • You need to quote the variables in the tests: [ -n "$var" ] etc. With -z it works without the quotes here, slightly accidentally, since if $var is empty in [ -z $var ], the expansion is just [ -z ] which just tests if -z is a nonempty string. The one with -n, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
          – ilkkachu
          Oct 29 '17 at 22:48











        • @ilkkachu, thx. It's fair remark, answer was changed
          – Egor Vasilyev
          Oct 30 '17 at 5:22













        up vote
        3
        down vote



        accepted







        up vote
        3
        down vote



        accepted






        Or other approach with smallest difference of your example:



        #!/bin/bash

        while read -r column1 column2 column3; do
        if [ -z "$column2" ] ; then
        printf '%sn' "Only first column has data"
        elif [ -z "$column3" ]; then
        printf '%sn' "Only first and second columns has data"
        elif [ -n "$column3" ]; then
        printf '%sn' "All three columns has data"
        fi
        done < file.txt


        Output will be:



        All three columns has data
        Only first and second columns has data
        Only first column has data


        Notes:



        In your example first and second lines contains several spaces at the end, but by default read removes all leading and trailing space characters.



        If your input contains more than 3 columns, all data in third column and further will placed in column3



        See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?






        share|improve this answer














        Or other approach with smallest difference of your example:



        #!/bin/bash

        while read -r column1 column2 column3; do
        if [ -z "$column2" ] ; then
        printf '%sn' "Only first column has data"
        elif [ -z "$column3" ]; then
        printf '%sn' "Only first and second columns has data"
        elif [ -n "$column3" ]; then
        printf '%sn' "All three columns has data"
        fi
        done < file.txt


        Output will be:



        All three columns has data
        Only first and second columns has data
        Only first column has data


        Notes:



        In your example first and second lines contains several spaces at the end, but by default read removes all leading and trailing space characters.



        If your input contains more than 3 columns, all data in third column and further will placed in column3



        See How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Oct 30 '17 at 5:19

























        answered Oct 29 '17 at 20:00









        Egor Vasilyev

        1,792129




        1,792129











        • You need to quote the variables in the tests: [ -n "$var" ] etc. With -z it works without the quotes here, slightly accidentally, since if $var is empty in [ -z $var ], the expansion is just [ -z ] which just tests if -z is a nonempty string. The one with -n, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
          – ilkkachu
          Oct 29 '17 at 22:48











        • @ilkkachu, thx. It's fair remark, answer was changed
          – Egor Vasilyev
          Oct 30 '17 at 5:22

















        • You need to quote the variables in the tests: [ -n "$var" ] etc. With -z it works without the quotes here, slightly accidentally, since if $var is empty in [ -z $var ], the expansion is just [ -z ] which just tests if -z is a nonempty string. The one with -n, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
          – ilkkachu
          Oct 29 '17 at 22:48











        • @ilkkachu, thx. It's fair remark, answer was changed
          – Egor Vasilyev
          Oct 30 '17 at 5:22
















        You need to quote the variables in the tests: [ -n "$var" ] etc. With -z it works without the quotes here, slightly accidentally, since if $var is empty in [ -z $var ], the expansion is just [ -z ] which just tests if -z is a nonempty string. The one with -n, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
        – ilkkachu
        Oct 29 '17 at 22:48





        You need to quote the variables in the tests: [ -n "$var" ] etc. With -z it works without the quotes here, slightly accidentally, since if $var is empty in [ -z $var ], the expansion is just [ -z ] which just tests if -z is a nonempty string. The one with -n, however, always gives a true result. (Of course whitespace and glob characters in the variable also cause a mess if the vars are unquoted.)
        – ilkkachu
        Oct 29 '17 at 22:48













        @ilkkachu, thx. It's fair remark, answer was changed
        – Egor Vasilyev
        Oct 30 '17 at 5:22





        @ilkkachu, thx. It's fair remark, answer was changed
        – Egor Vasilyev
        Oct 30 '17 at 5:22













        up vote
        1
        down vote













        You may read each line into array with read -ra, then, check the array size:



        fmt="Number of fields: %s. The last one: %sn"
        while read -ra items; do
        if [ $#items[*] == 3 ]; then
        printf "$fmt" $#items[*] $items[-1]
        elif [ $#items[*] == 2 ]; then
        printf "$fmt" $#items[*] $items[-1]
        elif [ $#items[*] == 1 ]; then
        printf "$fmt" $#items[*] $items[-1]
        fi
        done < file.txt



        Of course, expression printf "$fmt" $#items[*] $items[-1] was used just for demonstration, you can define your own.




        The above approach outputs(as an example):



        Number of fields: 3. The last one: cow
        Number of fields: 2. The last one: cucumber
        Number of fields: 1. The last one: banana





        share|improve this answer


























          up vote
          1
          down vote













          You may read each line into array with read -ra, then, check the array size:



          fmt="Number of fields: %s. The last one: %sn"
          while read -ra items; do
          if [ $#items[*] == 3 ]; then
          printf "$fmt" $#items[*] $items[-1]
          elif [ $#items[*] == 2 ]; then
          printf "$fmt" $#items[*] $items[-1]
          elif [ $#items[*] == 1 ]; then
          printf "$fmt" $#items[*] $items[-1]
          fi
          done < file.txt



          Of course, expression printf "$fmt" $#items[*] $items[-1] was used just for demonstration, you can define your own.




          The above approach outputs(as an example):



          Number of fields: 3. The last one: cow
          Number of fields: 2. The last one: cucumber
          Number of fields: 1. The last one: banana





          share|improve this answer
























            up vote
            1
            down vote










            up vote
            1
            down vote









            You may read each line into array with read -ra, then, check the array size:



            fmt="Number of fields: %s. The last one: %sn"
            while read -ra items; do
            if [ $#items[*] == 3 ]; then
            printf "$fmt" $#items[*] $items[-1]
            elif [ $#items[*] == 2 ]; then
            printf "$fmt" $#items[*] $items[-1]
            elif [ $#items[*] == 1 ]; then
            printf "$fmt" $#items[*] $items[-1]
            fi
            done < file.txt



            Of course, expression printf "$fmt" $#items[*] $items[-1] was used just for demonstration, you can define your own.




            The above approach outputs(as an example):



            Number of fields: 3. The last one: cow
            Number of fields: 2. The last one: cucumber
            Number of fields: 1. The last one: banana





            share|improve this answer














            You may read each line into array with read -ra, then, check the array size:



            fmt="Number of fields: %s. The last one: %sn"
            while read -ra items; do
            if [ $#items[*] == 3 ]; then
            printf "$fmt" $#items[*] $items[-1]
            elif [ $#items[*] == 2 ]; then
            printf "$fmt" $#items[*] $items[-1]
            elif [ $#items[*] == 1 ]; then
            printf "$fmt" $#items[*] $items[-1]
            fi
            done < file.txt



            Of course, expression printf "$fmt" $#items[*] $items[-1] was used just for demonstration, you can define your own.




            The above approach outputs(as an example):



            Number of fields: 3. The last one: cow
            Number of fields: 2. The last one: cucumber
            Number of fields: 1. The last one: banana






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Oct 29 '17 at 19:46

























            answered Oct 29 '17 at 19:32









            RomanPerekhrest

            22.5k12145




            22.5k12145




















                up vote
                1
                down vote













                while read -r column1 column2 column3; do
                if [ -z "$column2" ]; then
                # one column
                : command
                elif [ -z "$column3" ]; then
                # two columns
                : command
                else
                # three columns
                : command
                fi
                done < file.txt


                or



                while read -r column1 column2 column3; do
                set -- $column1 $column2 $column3
                case $# in
                1)
                : command
                ;;
                2)
                : command
                ;;
                *)
                : command
                ;;
                esac
                done < file.txt





                share|improve this answer
























                  up vote
                  1
                  down vote













                  while read -r column1 column2 column3; do
                  if [ -z "$column2" ]; then
                  # one column
                  : command
                  elif [ -z "$column3" ]; then
                  # two columns
                  : command
                  else
                  # three columns
                  : command
                  fi
                  done < file.txt


                  or



                  while read -r column1 column2 column3; do
                  set -- $column1 $column2 $column3
                  case $# in
                  1)
                  : command
                  ;;
                  2)
                  : command
                  ;;
                  *)
                  : command
                  ;;
                  esac
                  done < file.txt





                  share|improve this answer






















                    up vote
                    1
                    down vote










                    up vote
                    1
                    down vote









                    while read -r column1 column2 column3; do
                    if [ -z "$column2" ]; then
                    # one column
                    : command
                    elif [ -z "$column3" ]; then
                    # two columns
                    : command
                    else
                    # three columns
                    : command
                    fi
                    done < file.txt


                    or



                    while read -r column1 column2 column3; do
                    set -- $column1 $column2 $column3
                    case $# in
                    1)
                    : command
                    ;;
                    2)
                    : command
                    ;;
                    *)
                    : command
                    ;;
                    esac
                    done < file.txt





                    share|improve this answer












                    while read -r column1 column2 column3; do
                    if [ -z "$column2" ]; then
                    # one column
                    : command
                    elif [ -z "$column3" ]; then
                    # two columns
                    : command
                    else
                    # three columns
                    : command
                    fi
                    done < file.txt


                    or



                    while read -r column1 column2 column3; do
                    set -- $column1 $column2 $column3
                    case $# in
                    1)
                    : command
                    ;;
                    2)
                    : command
                    ;;
                    *)
                    : command
                    ;;
                    esac
                    done < file.txt






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Oct 29 '17 at 19:58









                    Hauke Laging

                    53.6k1282130




                    53.6k1282130




















                        up vote
                        0
                        down vote













                        Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash or ksh ( which also can be handy in case we do want to keep positional parameters). The below example is for bash ( note that for ksh or mksh you'd use -A insead of -a in read, and of course change #! line):



                        #!/usr/bin/env bash
                        line_counter=1
                        while read -r -a arr;
                        do
                        case "$#arr[@]" in
                        1) printf "One column in line %dn" "$line_counter";;
                        2) printf "Two columns in line %dn" "$line_counter";;
                        3) printf "Three columns in line %dn" "$line_counter";;
                        *) printf "More than 3 lines in line %dn" "$line_counter";;
                        esac
                        ((line_counter++))
                        done < input.txt


                        And the output is like so:



                        $ ./eval_columns.sh 
                        Three columns in line 1
                        Two columns in line 2
                        One column in line 3





                        share|improve this answer
























                          up vote
                          0
                          down vote













                          Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash or ksh ( which also can be handy in case we do want to keep positional parameters). The below example is for bash ( note that for ksh or mksh you'd use -A insead of -a in read, and of course change #! line):



                          #!/usr/bin/env bash
                          line_counter=1
                          while read -r -a arr;
                          do
                          case "$#arr[@]" in
                          1) printf "One column in line %dn" "$line_counter";;
                          2) printf "Two columns in line %dn" "$line_counter";;
                          3) printf "Three columns in line %dn" "$line_counter";;
                          *) printf "More than 3 lines in line %dn" "$line_counter";;
                          esac
                          ((line_counter++))
                          done < input.txt


                          And the output is like so:



                          $ ./eval_columns.sh 
                          Three columns in line 1
                          Two columns in line 2
                          One column in line 3





                          share|improve this answer






















                            up vote
                            0
                            down vote










                            up vote
                            0
                            down vote









                            Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash or ksh ( which also can be handy in case we do want to keep positional parameters). The below example is for bash ( note that for ksh or mksh you'd use -A insead of -a in read, and of course change #! line):



                            #!/usr/bin/env bash
                            line_counter=1
                            while read -r -a arr;
                            do
                            case "$#arr[@]" in
                            1) printf "One column in line %dn" "$line_counter";;
                            2) printf "Two columns in line %dn" "$line_counter";;
                            3) printf "Three columns in line %dn" "$line_counter";;
                            *) printf "More than 3 lines in line %dn" "$line_counter";;
                            esac
                            ((line_counter++))
                            done < input.txt


                            And the output is like so:



                            $ ./eval_columns.sh 
                            Three columns in line 1
                            Two columns in line 2
                            One column in line 3





                            share|improve this answer












                            Hauke Laging's answer already has a good idea of using evaluation via setting positional parameters and evaluating their number on each iteration. Variation on the theme can be done with use of arrays in bash or ksh ( which also can be handy in case we do want to keep positional parameters). The below example is for bash ( note that for ksh or mksh you'd use -A insead of -a in read, and of course change #! line):



                            #!/usr/bin/env bash
                            line_counter=1
                            while read -r -a arr;
                            do
                            case "$#arr[@]" in
                            1) printf "One column in line %dn" "$line_counter";;
                            2) printf "Two columns in line %dn" "$line_counter";;
                            3) printf "Three columns in line %dn" "$line_counter";;
                            *) printf "More than 3 lines in line %dn" "$line_counter";;
                            esac
                            ((line_counter++))
                            done < input.txt


                            And the output is like so:



                            $ ./eval_columns.sh 
                            Three columns in line 1
                            Two columns in line 2
                            One column in line 3






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Oct 30 '17 at 6:03









                            Sergiy Kolodyazhnyy

                            7,85811548




                            7,85811548



























                                 

                                draft saved


                                draft discarded















































                                 


                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function ()
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f401270%2fwhile-loop-and-if-statement-do-different-command-if-condition-is-met%23new-answer', 'question_page');

                                );

                                Post as a guest













































































                                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?