What does cut return if the specified field does not exist?

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











up vote
3
down vote

favorite












I have a string:



6.40.4


and a second one:



6.40


I am using var=$(echo $versionfull | cut -d'.' -f3) to get the third digit from the first string in bash. What does this command return for the second one? It looks empty but either [ -z $var ] or [ $var == "" ] does not work. I want to give it a value of 0 in case of a second string.







share|improve this question


















  • 2




    Pipe it to od to see what it returns...
    – don_crissti
    Aug 29 at 19:28














up vote
3
down vote

favorite












I have a string:



6.40.4


and a second one:



6.40


I am using var=$(echo $versionfull | cut -d'.' -f3) to get the third digit from the first string in bash. What does this command return for the second one? It looks empty but either [ -z $var ] or [ $var == "" ] does not work. I want to give it a value of 0 in case of a second string.







share|improve this question


















  • 2




    Pipe it to od to see what it returns...
    – don_crissti
    Aug 29 at 19:28












up vote
3
down vote

favorite









up vote
3
down vote

favorite











I have a string:



6.40.4


and a second one:



6.40


I am using var=$(echo $versionfull | cut -d'.' -f3) to get the third digit from the first string in bash. What does this command return for the second one? It looks empty but either [ -z $var ] or [ $var == "" ] does not work. I want to give it a value of 0 in case of a second string.







share|improve this question














I have a string:



6.40.4


and a second one:



6.40


I am using var=$(echo $versionfull | cut -d'.' -f3) to get the third digit from the first string in bash. What does this command return for the second one? It looks empty but either [ -z $var ] or [ $var == "" ] does not work. I want to give it a value of 0 in case of a second string.









share|improve this question













share|improve this question




share|improve this question








edited Aug 29 at 20:21









Jeff Schaller

32.1k849109




32.1k849109










asked Aug 29 at 19:17









Kliwer

182




182







  • 2




    Pipe it to od to see what it returns...
    – don_crissti
    Aug 29 at 19:28












  • 2




    Pipe it to od to see what it returns...
    – don_crissti
    Aug 29 at 19:28







2




2




Pipe it to od to see what it returns...
– don_crissti
Aug 29 at 19:28




Pipe it to od to see what it returns...
– don_crissti
Aug 29 at 19:28










4 Answers
4






active

oldest

votes

















up vote
8
down vote



accepted










You could use var=$(echo "$versionfull.0" | cut -d'.' -f3).



In the first case, versionfull will contain 6.40.4.0, ignoring the padding and returning 4 as needed. In the second case, the .0 will be padded and returned.






share|improve this answer






















  • Thanks. This is simple and works exactly like I want it to.
    – Kliwer
    Aug 29 at 19:39






  • 3




    It's sad that this is marked as the solution because it doesn't even answer the question, which is what everyone will expect to find when they come here in the future with the same question. Maybe the question should be changed to reflect that OP doesn't actually care about what it returns.
    – pipe
    Aug 30 at 9:28










  • You are right, it does not answers the question, but it solves OP problem. Is tailored for this only case, but that's all OP wants - solve his problem.
    – ThoriumBR
    Aug 30 at 11:43

















up vote
10
down vote













To answer your direct question, cut returns nothing except a trailing newline, as per the spec (thanks to don_crissti for that reference):



echo "$versionfull" | cut -d. -f3 | od -c
0000000 n
0000001


If you have a shell that supports here-strings, you could do the following:



IFS=. read a b c <<< "$versionfull"


Notice the quoting for $versionfull, in case it ever had whitespace (anything from $IFS).



If you think that c might be empty, then ask to set it to zero:



c=$c:-0





share|improve this answer


















  • 2




    Note that the need to quote in IFS=. read a b c <<< "$versionfull" was only for older versions of bash; other shells and newer versions of bash don't have the problem.
    – Stéphane Chazelas
    Aug 29 at 19:43










  • Note that if the input has only one field, cut returns that field.
    – Stéphane Chazelas
    Aug 29 at 20:05

















up vote
6
down vote













cut has an odd API.



cut -f n will output the nth field of each line that has at least one delimiter (empty if the line has fewer than n-1 delimiters (fewer than n fields)), and returns the full line (so the first field) for those that don't have any delimiter:



$ echo a.b.c | cut -d. -f3
c
$ echo a.b | cut -d. -f3

$ echo a | cut -d. -f3
a


So the answer to What does cut return if the specified field does not exist? is either the first field or an empty field depending on whether the input line has one field or more.



You can add the -s option to remove the lines that don't have any delimiter to avoid that weird last case above, but that's generally not what you want (you'd generally want to consider that input line to have an empty 3rd field instead of skipping it altogether), and that's worth if you want the first field:



$ echo a | cut -sd. -f2
$ echo a | cut -sd. -f1
$


(you asked for the first field, the input has only one field, but you don't get any output because the input has no delimiter).



So @ThoriumBR's suggestion to add a .0 is a very good one. Without it:



versionfull=5
echo "$versionfull" | cut -d. -f3


would actually output 5. By adding .0, we make sure the input has at least one delimiter. I would go further and use:



echo "$versionfull.0.0" | cut -d. -f3


To make sure the input has at least 3 fields.






share|improve this answer






















  • The probability of version 7 in Mikrotik is low ;) Anyway, thanks - I'll do that.
    – Kliwer
    Aug 29 at 20:11










  • How does this relate to his second case? The input has a delimiter.
    – Barmar
    Aug 29 at 22:59

















up vote
1
down vote













It sets it to an empty string. You should quote the variable when using it with the [ command.



if [ "$var" == "" ]
then echo "Var is empty"
fi


Without the quotes, the first line expands to:



if [ == "" ]


which is invalid syntax because == requires a parameter to the left of it.






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%2f465583%2fwhat-does-cut-return-if-the-specified-field-does-not-exist%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
    8
    down vote



    accepted










    You could use var=$(echo "$versionfull.0" | cut -d'.' -f3).



    In the first case, versionfull will contain 6.40.4.0, ignoring the padding and returning 4 as needed. In the second case, the .0 will be padded and returned.






    share|improve this answer






















    • Thanks. This is simple and works exactly like I want it to.
      – Kliwer
      Aug 29 at 19:39






    • 3




      It's sad that this is marked as the solution because it doesn't even answer the question, which is what everyone will expect to find when they come here in the future with the same question. Maybe the question should be changed to reflect that OP doesn't actually care about what it returns.
      – pipe
      Aug 30 at 9:28










    • You are right, it does not answers the question, but it solves OP problem. Is tailored for this only case, but that's all OP wants - solve his problem.
      – ThoriumBR
      Aug 30 at 11:43














    up vote
    8
    down vote



    accepted










    You could use var=$(echo "$versionfull.0" | cut -d'.' -f3).



    In the first case, versionfull will contain 6.40.4.0, ignoring the padding and returning 4 as needed. In the second case, the .0 will be padded and returned.






    share|improve this answer






















    • Thanks. This is simple and works exactly like I want it to.
      – Kliwer
      Aug 29 at 19:39






    • 3




      It's sad that this is marked as the solution because it doesn't even answer the question, which is what everyone will expect to find when they come here in the future with the same question. Maybe the question should be changed to reflect that OP doesn't actually care about what it returns.
      – pipe
      Aug 30 at 9:28










    • You are right, it does not answers the question, but it solves OP problem. Is tailored for this only case, but that's all OP wants - solve his problem.
      – ThoriumBR
      Aug 30 at 11:43












    up vote
    8
    down vote



    accepted







    up vote
    8
    down vote



    accepted






    You could use var=$(echo "$versionfull.0" | cut -d'.' -f3).



    In the first case, versionfull will contain 6.40.4.0, ignoring the padding and returning 4 as needed. In the second case, the .0 will be padded and returned.






    share|improve this answer














    You could use var=$(echo "$versionfull.0" | cut -d'.' -f3).



    In the first case, versionfull will contain 6.40.4.0, ignoring the padding and returning 4 as needed. In the second case, the .0 will be padded and returned.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 29 at 20:09









    Stéphane Chazelas

    283k53521856




    283k53521856










    answered Aug 29 at 19:26









    ThoriumBR

    1984




    1984











    • Thanks. This is simple and works exactly like I want it to.
      – Kliwer
      Aug 29 at 19:39






    • 3




      It's sad that this is marked as the solution because it doesn't even answer the question, which is what everyone will expect to find when they come here in the future with the same question. Maybe the question should be changed to reflect that OP doesn't actually care about what it returns.
      – pipe
      Aug 30 at 9:28










    • You are right, it does not answers the question, but it solves OP problem. Is tailored for this only case, but that's all OP wants - solve his problem.
      – ThoriumBR
      Aug 30 at 11:43
















    • Thanks. This is simple and works exactly like I want it to.
      – Kliwer
      Aug 29 at 19:39






    • 3




      It's sad that this is marked as the solution because it doesn't even answer the question, which is what everyone will expect to find when they come here in the future with the same question. Maybe the question should be changed to reflect that OP doesn't actually care about what it returns.
      – pipe
      Aug 30 at 9:28










    • You are right, it does not answers the question, but it solves OP problem. Is tailored for this only case, but that's all OP wants - solve his problem.
      – ThoriumBR
      Aug 30 at 11:43















    Thanks. This is simple and works exactly like I want it to.
    – Kliwer
    Aug 29 at 19:39




    Thanks. This is simple and works exactly like I want it to.
    – Kliwer
    Aug 29 at 19:39




    3




    3




    It's sad that this is marked as the solution because it doesn't even answer the question, which is what everyone will expect to find when they come here in the future with the same question. Maybe the question should be changed to reflect that OP doesn't actually care about what it returns.
    – pipe
    Aug 30 at 9:28




    It's sad that this is marked as the solution because it doesn't even answer the question, which is what everyone will expect to find when they come here in the future with the same question. Maybe the question should be changed to reflect that OP doesn't actually care about what it returns.
    – pipe
    Aug 30 at 9:28












    You are right, it does not answers the question, but it solves OP problem. Is tailored for this only case, but that's all OP wants - solve his problem.
    – ThoriumBR
    Aug 30 at 11:43




    You are right, it does not answers the question, but it solves OP problem. Is tailored for this only case, but that's all OP wants - solve his problem.
    – ThoriumBR
    Aug 30 at 11:43












    up vote
    10
    down vote













    To answer your direct question, cut returns nothing except a trailing newline, as per the spec (thanks to don_crissti for that reference):



    echo "$versionfull" | cut -d. -f3 | od -c
    0000000 n
    0000001


    If you have a shell that supports here-strings, you could do the following:



    IFS=. read a b c <<< "$versionfull"


    Notice the quoting for $versionfull, in case it ever had whitespace (anything from $IFS).



    If you think that c might be empty, then ask to set it to zero:



    c=$c:-0





    share|improve this answer


















    • 2




      Note that the need to quote in IFS=. read a b c <<< "$versionfull" was only for older versions of bash; other shells and newer versions of bash don't have the problem.
      – Stéphane Chazelas
      Aug 29 at 19:43










    • Note that if the input has only one field, cut returns that field.
      – Stéphane Chazelas
      Aug 29 at 20:05














    up vote
    10
    down vote













    To answer your direct question, cut returns nothing except a trailing newline, as per the spec (thanks to don_crissti for that reference):



    echo "$versionfull" | cut -d. -f3 | od -c
    0000000 n
    0000001


    If you have a shell that supports here-strings, you could do the following:



    IFS=. read a b c <<< "$versionfull"


    Notice the quoting for $versionfull, in case it ever had whitespace (anything from $IFS).



    If you think that c might be empty, then ask to set it to zero:



    c=$c:-0





    share|improve this answer


















    • 2




      Note that the need to quote in IFS=. read a b c <<< "$versionfull" was only for older versions of bash; other shells and newer versions of bash don't have the problem.
      – Stéphane Chazelas
      Aug 29 at 19:43










    • Note that if the input has only one field, cut returns that field.
      – Stéphane Chazelas
      Aug 29 at 20:05












    up vote
    10
    down vote










    up vote
    10
    down vote









    To answer your direct question, cut returns nothing except a trailing newline, as per the spec (thanks to don_crissti for that reference):



    echo "$versionfull" | cut -d. -f3 | od -c
    0000000 n
    0000001


    If you have a shell that supports here-strings, you could do the following:



    IFS=. read a b c <<< "$versionfull"


    Notice the quoting for $versionfull, in case it ever had whitespace (anything from $IFS).



    If you think that c might be empty, then ask to set it to zero:



    c=$c:-0





    share|improve this answer














    To answer your direct question, cut returns nothing except a trailing newline, as per the spec (thanks to don_crissti for that reference):



    echo "$versionfull" | cut -d. -f3 | od -c
    0000000 n
    0000001


    If you have a shell that supports here-strings, you could do the following:



    IFS=. read a b c <<< "$versionfull"


    Notice the quoting for $versionfull, in case it ever had whitespace (anything from $IFS).



    If you think that c might be empty, then ask to set it to zero:



    c=$c:-0






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 29 at 19:49

























    answered Aug 29 at 19:27









    Jeff Schaller

    32.1k849109




    32.1k849109







    • 2




      Note that the need to quote in IFS=. read a b c <<< "$versionfull" was only for older versions of bash; other shells and newer versions of bash don't have the problem.
      – Stéphane Chazelas
      Aug 29 at 19:43










    • Note that if the input has only one field, cut returns that field.
      – Stéphane Chazelas
      Aug 29 at 20:05












    • 2




      Note that the need to quote in IFS=. read a b c <<< "$versionfull" was only for older versions of bash; other shells and newer versions of bash don't have the problem.
      – Stéphane Chazelas
      Aug 29 at 19:43










    • Note that if the input has only one field, cut returns that field.
      – Stéphane Chazelas
      Aug 29 at 20:05







    2




    2




    Note that the need to quote in IFS=. read a b c <<< "$versionfull" was only for older versions of bash; other shells and newer versions of bash don't have the problem.
    – Stéphane Chazelas
    Aug 29 at 19:43




    Note that the need to quote in IFS=. read a b c <<< "$versionfull" was only for older versions of bash; other shells and newer versions of bash don't have the problem.
    – Stéphane Chazelas
    Aug 29 at 19:43












    Note that if the input has only one field, cut returns that field.
    – Stéphane Chazelas
    Aug 29 at 20:05




    Note that if the input has only one field, cut returns that field.
    – Stéphane Chazelas
    Aug 29 at 20:05










    up vote
    6
    down vote













    cut has an odd API.



    cut -f n will output the nth field of each line that has at least one delimiter (empty if the line has fewer than n-1 delimiters (fewer than n fields)), and returns the full line (so the first field) for those that don't have any delimiter:



    $ echo a.b.c | cut -d. -f3
    c
    $ echo a.b | cut -d. -f3

    $ echo a | cut -d. -f3
    a


    So the answer to What does cut return if the specified field does not exist? is either the first field or an empty field depending on whether the input line has one field or more.



    You can add the -s option to remove the lines that don't have any delimiter to avoid that weird last case above, but that's generally not what you want (you'd generally want to consider that input line to have an empty 3rd field instead of skipping it altogether), and that's worth if you want the first field:



    $ echo a | cut -sd. -f2
    $ echo a | cut -sd. -f1
    $


    (you asked for the first field, the input has only one field, but you don't get any output because the input has no delimiter).



    So @ThoriumBR's suggestion to add a .0 is a very good one. Without it:



    versionfull=5
    echo "$versionfull" | cut -d. -f3


    would actually output 5. By adding .0, we make sure the input has at least one delimiter. I would go further and use:



    echo "$versionfull.0.0" | cut -d. -f3


    To make sure the input has at least 3 fields.






    share|improve this answer






















    • The probability of version 7 in Mikrotik is low ;) Anyway, thanks - I'll do that.
      – Kliwer
      Aug 29 at 20:11










    • How does this relate to his second case? The input has a delimiter.
      – Barmar
      Aug 29 at 22:59














    up vote
    6
    down vote













    cut has an odd API.



    cut -f n will output the nth field of each line that has at least one delimiter (empty if the line has fewer than n-1 delimiters (fewer than n fields)), and returns the full line (so the first field) for those that don't have any delimiter:



    $ echo a.b.c | cut -d. -f3
    c
    $ echo a.b | cut -d. -f3

    $ echo a | cut -d. -f3
    a


    So the answer to What does cut return if the specified field does not exist? is either the first field or an empty field depending on whether the input line has one field or more.



    You can add the -s option to remove the lines that don't have any delimiter to avoid that weird last case above, but that's generally not what you want (you'd generally want to consider that input line to have an empty 3rd field instead of skipping it altogether), and that's worth if you want the first field:



    $ echo a | cut -sd. -f2
    $ echo a | cut -sd. -f1
    $


    (you asked for the first field, the input has only one field, but you don't get any output because the input has no delimiter).



    So @ThoriumBR's suggestion to add a .0 is a very good one. Without it:



    versionfull=5
    echo "$versionfull" | cut -d. -f3


    would actually output 5. By adding .0, we make sure the input has at least one delimiter. I would go further and use:



    echo "$versionfull.0.0" | cut -d. -f3


    To make sure the input has at least 3 fields.






    share|improve this answer






















    • The probability of version 7 in Mikrotik is low ;) Anyway, thanks - I'll do that.
      – Kliwer
      Aug 29 at 20:11










    • How does this relate to his second case? The input has a delimiter.
      – Barmar
      Aug 29 at 22:59












    up vote
    6
    down vote










    up vote
    6
    down vote









    cut has an odd API.



    cut -f n will output the nth field of each line that has at least one delimiter (empty if the line has fewer than n-1 delimiters (fewer than n fields)), and returns the full line (so the first field) for those that don't have any delimiter:



    $ echo a.b.c | cut -d. -f3
    c
    $ echo a.b | cut -d. -f3

    $ echo a | cut -d. -f3
    a


    So the answer to What does cut return if the specified field does not exist? is either the first field or an empty field depending on whether the input line has one field or more.



    You can add the -s option to remove the lines that don't have any delimiter to avoid that weird last case above, but that's generally not what you want (you'd generally want to consider that input line to have an empty 3rd field instead of skipping it altogether), and that's worth if you want the first field:



    $ echo a | cut -sd. -f2
    $ echo a | cut -sd. -f1
    $


    (you asked for the first field, the input has only one field, but you don't get any output because the input has no delimiter).



    So @ThoriumBR's suggestion to add a .0 is a very good one. Without it:



    versionfull=5
    echo "$versionfull" | cut -d. -f3


    would actually output 5. By adding .0, we make sure the input has at least one delimiter. I would go further and use:



    echo "$versionfull.0.0" | cut -d. -f3


    To make sure the input has at least 3 fields.






    share|improve this answer














    cut has an odd API.



    cut -f n will output the nth field of each line that has at least one delimiter (empty if the line has fewer than n-1 delimiters (fewer than n fields)), and returns the full line (so the first field) for those that don't have any delimiter:



    $ echo a.b.c | cut -d. -f3
    c
    $ echo a.b | cut -d. -f3

    $ echo a | cut -d. -f3
    a


    So the answer to What does cut return if the specified field does not exist? is either the first field or an empty field depending on whether the input line has one field or more.



    You can add the -s option to remove the lines that don't have any delimiter to avoid that weird last case above, but that's generally not what you want (you'd generally want to consider that input line to have an empty 3rd field instead of skipping it altogether), and that's worth if you want the first field:



    $ echo a | cut -sd. -f2
    $ echo a | cut -sd. -f1
    $


    (you asked for the first field, the input has only one field, but you don't get any output because the input has no delimiter).



    So @ThoriumBR's suggestion to add a .0 is a very good one. Without it:



    versionfull=5
    echo "$versionfull" | cut -d. -f3


    would actually output 5. By adding .0, we make sure the input has at least one delimiter. I would go further and use:



    echo "$versionfull.0.0" | cut -d. -f3


    To make sure the input has at least 3 fields.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Aug 30 at 6:40

























    answered Aug 29 at 20:02









    Stéphane Chazelas

    283k53521856




    283k53521856











    • The probability of version 7 in Mikrotik is low ;) Anyway, thanks - I'll do that.
      – Kliwer
      Aug 29 at 20:11










    • How does this relate to his second case? The input has a delimiter.
      – Barmar
      Aug 29 at 22:59
















    • The probability of version 7 in Mikrotik is low ;) Anyway, thanks - I'll do that.
      – Kliwer
      Aug 29 at 20:11










    • How does this relate to his second case? The input has a delimiter.
      – Barmar
      Aug 29 at 22:59















    The probability of version 7 in Mikrotik is low ;) Anyway, thanks - I'll do that.
    – Kliwer
    Aug 29 at 20:11




    The probability of version 7 in Mikrotik is low ;) Anyway, thanks - I'll do that.
    – Kliwer
    Aug 29 at 20:11












    How does this relate to his second case? The input has a delimiter.
    – Barmar
    Aug 29 at 22:59




    How does this relate to his second case? The input has a delimiter.
    – Barmar
    Aug 29 at 22:59










    up vote
    1
    down vote













    It sets it to an empty string. You should quote the variable when using it with the [ command.



    if [ "$var" == "" ]
    then echo "Var is empty"
    fi


    Without the quotes, the first line expands to:



    if [ == "" ]


    which is invalid syntax because == requires a parameter to the left of it.






    share|improve this answer
























      up vote
      1
      down vote













      It sets it to an empty string. You should quote the variable when using it with the [ command.



      if [ "$var" == "" ]
      then echo "Var is empty"
      fi


      Without the quotes, the first line expands to:



      if [ == "" ]


      which is invalid syntax because == requires a parameter to the left of it.






      share|improve this answer






















        up vote
        1
        down vote










        up vote
        1
        down vote









        It sets it to an empty string. You should quote the variable when using it with the [ command.



        if [ "$var" == "" ]
        then echo "Var is empty"
        fi


        Without the quotes, the first line expands to:



        if [ == "" ]


        which is invalid syntax because == requires a parameter to the left of it.






        share|improve this answer












        It sets it to an empty string. You should quote the variable when using it with the [ command.



        if [ "$var" == "" ]
        then echo "Var is empty"
        fi


        Without the quotes, the first line expands to:



        if [ == "" ]


        which is invalid syntax because == requires a parameter to the left of it.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Aug 29 at 23:03









        Barmar

        6,7201122




        6,7201122



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f465583%2fwhat-does-cut-return-if-the-specified-field-does-not-exist%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            What does second last employer means? [closed]

            Installing NextGIS Connect into QGIS 3?

            One-line joke