Colon character is messing up my pattern match in Bash












1














I have a variable $line, which can contain any of the following strings:





  • line="READ CACHE IS: ENABLED"


  • line="BLOCKS READ CACHE AND SENT TO INITIATOR = 2489338280"

  • line="ECC REREADS/ ERRORS ALGORITHM PROCESSED UNCORRECTED"


  • line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"


  • line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"


  • line="0x22 GPL R/O 1 READ STREAM ERROR LOG"

  • line="READ: DISABLED"


I have a script that compares the $line variable against some patterns:



if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')


Herein lies the problem. The colon is screwing everything up. I've tried every possible way of formatting the pattern to satisfy both possibilities of line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" or line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0" When I escape the : as shown above. I can satisfy line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" but not line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0". If I take away the escape, then I satisfy line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"not line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"



Sample Run 1:



line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 1:



0


Sample Run 2:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 2:



<null>


Sample Run 3:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 3:



0


How do I get the best of both worlds?










share|improve this question
























  • These are all separate expressions; I don't see how changing one causes a different one to break. Can you edit in separate examples of each case that isn't working?
    – Michael Homer
    Sep 19 '18 at 2:59






  • 1




    @AfroJoe : I don't see the usage of regular expressions in your post. Note that regular expressions in bash are tested using the =~ operator, not == (which matches against file expansion),
    – user1934428
    Sep 19 '18 at 6:35












  • @MichaelHomer EDITED: with sample runs. (copy/paste and try yourself) :)
    – AfroJoe
    Sep 19 '18 at 13:06










  • What's the problem with the third one? It matches the pattern READ:*, and prints the eighth field, which is 0.
    – ilkkachu
    Sep 19 '18 at 13:18










  • The problem is the program loops through all the possible values of $line (indicated above) and writes $devReadErr as <null> upon encountering READ: 2513550726 22 0 2513550748 2513550748 27768.965 0 when the colon is escaped.
    – AfroJoe
    Sep 19 '18 at 13:47
















1














I have a variable $line, which can contain any of the following strings:





  • line="READ CACHE IS: ENABLED"


  • line="BLOCKS READ CACHE AND SENT TO INITIATOR = 2489338280"

  • line="ECC REREADS/ ERRORS ALGORITHM PROCESSED UNCORRECTED"


  • line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"


  • line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"


  • line="0x22 GPL R/O 1 READ STREAM ERROR LOG"

  • line="READ: DISABLED"


I have a script that compares the $line variable against some patterns:



if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')


Herein lies the problem. The colon is screwing everything up. I've tried every possible way of formatting the pattern to satisfy both possibilities of line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" or line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0" When I escape the : as shown above. I can satisfy line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" but not line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0". If I take away the escape, then I satisfy line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"not line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"



Sample Run 1:



line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 1:



0


Sample Run 2:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 2:



<null>


Sample Run 3:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 3:



0


How do I get the best of both worlds?










share|improve this question
























  • These are all separate expressions; I don't see how changing one causes a different one to break. Can you edit in separate examples of each case that isn't working?
    – Michael Homer
    Sep 19 '18 at 2:59






  • 1




    @AfroJoe : I don't see the usage of regular expressions in your post. Note that regular expressions in bash are tested using the =~ operator, not == (which matches against file expansion),
    – user1934428
    Sep 19 '18 at 6:35












  • @MichaelHomer EDITED: with sample runs. (copy/paste and try yourself) :)
    – AfroJoe
    Sep 19 '18 at 13:06










  • What's the problem with the third one? It matches the pattern READ:*, and prints the eighth field, which is 0.
    – ilkkachu
    Sep 19 '18 at 13:18










  • The problem is the program loops through all the possible values of $line (indicated above) and writes $devReadErr as <null> upon encountering READ: 2513550726 22 0 2513550748 2513550748 27768.965 0 when the colon is escaped.
    – AfroJoe
    Sep 19 '18 at 13:47














1












1








1







I have a variable $line, which can contain any of the following strings:





  • line="READ CACHE IS: ENABLED"


  • line="BLOCKS READ CACHE AND SENT TO INITIATOR = 2489338280"

  • line="ECC REREADS/ ERRORS ALGORITHM PROCESSED UNCORRECTED"


  • line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"


  • line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"


  • line="0x22 GPL R/O 1 READ STREAM ERROR LOG"

  • line="READ: DISABLED"


I have a script that compares the $line variable against some patterns:



if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')


Herein lies the problem. The colon is screwing everything up. I've tried every possible way of formatting the pattern to satisfy both possibilities of line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" or line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0" When I escape the : as shown above. I can satisfy line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" but not line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0". If I take away the escape, then I satisfy line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"not line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"



Sample Run 1:



line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 1:



0


Sample Run 2:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 2:



<null>


Sample Run 3:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 3:



0


How do I get the best of both worlds?










share|improve this question















I have a variable $line, which can contain any of the following strings:





  • line="READ CACHE IS: ENABLED"


  • line="BLOCKS READ CACHE AND SENT TO INITIATOR = 2489338280"

  • line="ECC REREADS/ ERRORS ALGORITHM PROCESSED UNCORRECTED"


  • line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"


  • line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"


  • line="0x22 GPL R/O 1 READ STREAM ERROR LOG"

  • line="READ: DISABLED"


I have a script that compares the $line variable against some patterns:



if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] || 
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')


Herein lies the problem. The colon is screwing everything up. I've tried every possible way of formatting the pattern to satisfy both possibilities of line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" or line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0" When I escape the : as shown above. I can satisfy line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0" but not line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0". If I take away the escape, then I satisfy line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"not line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"



Sample Run 1:



line="1 RAW_READ_ERROR_RATE PO-R-- 100 100 016 - 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 1:



0


Sample Run 2:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 2:



<null>


Sample Run 3:



line="READ: 2513550726 22 0 2513550748 2513550748 27768.965 0"

if [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $8}')
fi

echo $devReadErr


Output of Run 3:



0


How do I get the best of both worlds?







bash wildcards






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 15 mins ago









Rui F Ribeiro

39.2k1479130




39.2k1479130










asked Sep 19 '18 at 2:18









AfroJoe

42518




42518












  • These are all separate expressions; I don't see how changing one causes a different one to break. Can you edit in separate examples of each case that isn't working?
    – Michael Homer
    Sep 19 '18 at 2:59






  • 1




    @AfroJoe : I don't see the usage of regular expressions in your post. Note that regular expressions in bash are tested using the =~ operator, not == (which matches against file expansion),
    – user1934428
    Sep 19 '18 at 6:35












  • @MichaelHomer EDITED: with sample runs. (copy/paste and try yourself) :)
    – AfroJoe
    Sep 19 '18 at 13:06










  • What's the problem with the third one? It matches the pattern READ:*, and prints the eighth field, which is 0.
    – ilkkachu
    Sep 19 '18 at 13:18










  • The problem is the program loops through all the possible values of $line (indicated above) and writes $devReadErr as <null> upon encountering READ: 2513550726 22 0 2513550748 2513550748 27768.965 0 when the colon is escaped.
    – AfroJoe
    Sep 19 '18 at 13:47


















  • These are all separate expressions; I don't see how changing one causes a different one to break. Can you edit in separate examples of each case that isn't working?
    – Michael Homer
    Sep 19 '18 at 2:59






  • 1




    @AfroJoe : I don't see the usage of regular expressions in your post. Note that regular expressions in bash are tested using the =~ operator, not == (which matches against file expansion),
    – user1934428
    Sep 19 '18 at 6:35












  • @MichaelHomer EDITED: with sample runs. (copy/paste and try yourself) :)
    – AfroJoe
    Sep 19 '18 at 13:06










  • What's the problem with the third one? It matches the pattern READ:*, and prints the eighth field, which is 0.
    – ilkkachu
    Sep 19 '18 at 13:18










  • The problem is the program loops through all the possible values of $line (indicated above) and writes $devReadErr as <null> upon encountering READ: 2513550726 22 0 2513550748 2513550748 27768.965 0 when the colon is escaped.
    – AfroJoe
    Sep 19 '18 at 13:47
















These are all separate expressions; I don't see how changing one causes a different one to break. Can you edit in separate examples of each case that isn't working?
– Michael Homer
Sep 19 '18 at 2:59




These are all separate expressions; I don't see how changing one causes a different one to break. Can you edit in separate examples of each case that isn't working?
– Michael Homer
Sep 19 '18 at 2:59




1




1




@AfroJoe : I don't see the usage of regular expressions in your post. Note that regular expressions in bash are tested using the =~ operator, not == (which matches against file expansion),
– user1934428
Sep 19 '18 at 6:35






@AfroJoe : I don't see the usage of regular expressions in your post. Note that regular expressions in bash are tested using the =~ operator, not == (which matches against file expansion),
– user1934428
Sep 19 '18 at 6:35














@MichaelHomer EDITED: with sample runs. (copy/paste and try yourself) :)
– AfroJoe
Sep 19 '18 at 13:06




@MichaelHomer EDITED: with sample runs. (copy/paste and try yourself) :)
– AfroJoe
Sep 19 '18 at 13:06












What's the problem with the third one? It matches the pattern READ:*, and prints the eighth field, which is 0.
– ilkkachu
Sep 19 '18 at 13:18




What's the problem with the third one? It matches the pattern READ:*, and prints the eighth field, which is 0.
– ilkkachu
Sep 19 '18 at 13:18












The problem is the program loops through all the possible values of $line (indicated above) and writes $devReadErr as <null> upon encountering READ: 2513550726 22 0 2513550748 2513550748 27768.965 0 when the colon is escaped.
– AfroJoe
Sep 19 '18 at 13:47




The problem is the program loops through all the possible values of $line (indicated above) and writes $devReadErr as <null> upon encountering READ: 2513550726 22 0 2513550748 2513550748 27768.965 0 when the colon is escaped.
– AfroJoe
Sep 19 '18 at 13:47










2 Answers
2






active

oldest

votes


















2














You should remove the in front of : in that second test, or it will try to match against a literal character.



These are not regular expression matches you are doing, but shell globbing pattern matches (just as on the command line when you are using * in patterns). This doesn't really matter in this case.



I'm assuming that you'd like to extract the 20 from the two first strings and store it in devReadErr, but not when the line reads READ: DISABLED. This is exactly what your code does if the is removed:



if  [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
[[ ${line} == "READ:"* ]] &&
[[ ${line} != *"READ: DISABLED"* ]]; then

devReadErr=$(echo "$line" | awk '{print $2}')

fi


Another way to do the same thing:



if [[ "$line" != *'DISABLED' ]]; then
devReadErr=${line##* }
fi


This extracts the number as the string after the last space character in $line if the string does not end with the word DISABLED. This avoids the echo and awk.



If this is part of a larger loop that parses a file line by line, then I would suggest writing it in awk or some other language designed to parse text. See, e.g., Why is using a shell loop to process text considered bad practice?.






share|improve this answer





















  • I edited the question with way more detail and sample runs. As you indicated Kusalananda, its apart of a larger loop. The use of awk is definitely an option, but I'd like to see if the collective can figure out the underlying behaviour of how BASH is working towards processing the expression.
    – AfroJoe
    Sep 19 '18 at 13:09



















0














I suspect you want:



if [[ $line = *RAW_READ_ERROR_RATE* || 
$line = READ:* && $line != *"READ: DISABLED"* ]]; then


The && [[...]] operator has precedence over || but the && shell operator has same precedence as ||.



Or to make it explicit:



if [[ $line = *RAW_READ_ERROR_RATE* || 
($line = READ:* && $line != *"READ: DISABLED"*) ]]; then


Or using the &&/|| shell operators and multiple [[...]]s:



if [[ $line = *RAW_READ_ERROR_RATE* ]] || { 
[[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]]; }; then


Or change the order:



if [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]] ||
[[ $line = *RAW_READ_ERROR_RATE* ]]; then


Or use a pattern that matches all:



if [[ $line = @(*RAW_READ_ERROR_RATE*|!(!(*READ:*)|*READ: DISABLED*)) ]]; then


Without the parenthesis/braces, yours is read as:



if [[ ($line = *RAW_READ_ERROR_RATE* || 
$line = READ:*) && $line != *"READ: DISABLED"* ]]; then


That shouldn't prevent it from matching lines that contain RAW_READ_ERROR_RATE though provided they don't contain READ: DISABLED.






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%2f469914%2fcolon-character-is-messing-up-my-pattern-match-in-bash%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    You should remove the in front of : in that second test, or it will try to match against a literal character.



    These are not regular expression matches you are doing, but shell globbing pattern matches (just as on the command line when you are using * in patterns). This doesn't really matter in this case.



    I'm assuming that you'd like to extract the 20 from the two first strings and store it in devReadErr, but not when the line reads READ: DISABLED. This is exactly what your code does if the is removed:



    if  [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
    [[ ${line} == "READ:"* ]] &&
    [[ ${line} != *"READ: DISABLED"* ]]; then

    devReadErr=$(echo "$line" | awk '{print $2}')

    fi


    Another way to do the same thing:



    if [[ "$line" != *'DISABLED' ]]; then
    devReadErr=${line##* }
    fi


    This extracts the number as the string after the last space character in $line if the string does not end with the word DISABLED. This avoids the echo and awk.



    If this is part of a larger loop that parses a file line by line, then I would suggest writing it in awk or some other language designed to parse text. See, e.g., Why is using a shell loop to process text considered bad practice?.






    share|improve this answer





















    • I edited the question with way more detail and sample runs. As you indicated Kusalananda, its apart of a larger loop. The use of awk is definitely an option, but I'd like to see if the collective can figure out the underlying behaviour of how BASH is working towards processing the expression.
      – AfroJoe
      Sep 19 '18 at 13:09
















    2














    You should remove the in front of : in that second test, or it will try to match against a literal character.



    These are not regular expression matches you are doing, but shell globbing pattern matches (just as on the command line when you are using * in patterns). This doesn't really matter in this case.



    I'm assuming that you'd like to extract the 20 from the two first strings and store it in devReadErr, but not when the line reads READ: DISABLED. This is exactly what your code does if the is removed:



    if  [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
    [[ ${line} == "READ:"* ]] &&
    [[ ${line} != *"READ: DISABLED"* ]]; then

    devReadErr=$(echo "$line" | awk '{print $2}')

    fi


    Another way to do the same thing:



    if [[ "$line" != *'DISABLED' ]]; then
    devReadErr=${line##* }
    fi


    This extracts the number as the string after the last space character in $line if the string does not end with the word DISABLED. This avoids the echo and awk.



    If this is part of a larger loop that parses a file line by line, then I would suggest writing it in awk or some other language designed to parse text. See, e.g., Why is using a shell loop to process text considered bad practice?.






    share|improve this answer





















    • I edited the question with way more detail and sample runs. As you indicated Kusalananda, its apart of a larger loop. The use of awk is definitely an option, but I'd like to see if the collective can figure out the underlying behaviour of how BASH is working towards processing the expression.
      – AfroJoe
      Sep 19 '18 at 13:09














    2












    2








    2






    You should remove the in front of : in that second test, or it will try to match against a literal character.



    These are not regular expression matches you are doing, but shell globbing pattern matches (just as on the command line when you are using * in patterns). This doesn't really matter in this case.



    I'm assuming that you'd like to extract the 20 from the two first strings and store it in devReadErr, but not when the line reads READ: DISABLED. This is exactly what your code does if the is removed:



    if  [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
    [[ ${line} == "READ:"* ]] &&
    [[ ${line} != *"READ: DISABLED"* ]]; then

    devReadErr=$(echo "$line" | awk '{print $2}')

    fi


    Another way to do the same thing:



    if [[ "$line" != *'DISABLED' ]]; then
    devReadErr=${line##* }
    fi


    This extracts the number as the string after the last space character in $line if the string does not end with the word DISABLED. This avoids the echo and awk.



    If this is part of a larger loop that parses a file line by line, then I would suggest writing it in awk or some other language designed to parse text. See, e.g., Why is using a shell loop to process text considered bad practice?.






    share|improve this answer












    You should remove the in front of : in that second test, or it will try to match against a literal character.



    These are not regular expression matches you are doing, but shell globbing pattern matches (just as on the command line when you are using * in patterns). This doesn't really matter in this case.



    I'm assuming that you'd like to extract the 20 from the two first strings and store it in devReadErr, but not when the line reads READ: DISABLED. This is exactly what your code does if the is removed:



    if  [[ ${line} == *"RAW_READ_ERROR_RATE"* ]] ||
    [[ ${line} == "READ:"* ]] &&
    [[ ${line} != *"READ: DISABLED"* ]]; then

    devReadErr=$(echo "$line" | awk '{print $2}')

    fi


    Another way to do the same thing:



    if [[ "$line" != *'DISABLED' ]]; then
    devReadErr=${line##* }
    fi


    This extracts the number as the string after the last space character in $line if the string does not end with the word DISABLED. This avoids the echo and awk.



    If this is part of a larger loop that parses a file line by line, then I would suggest writing it in awk or some other language designed to parse text. See, e.g., Why is using a shell loop to process text considered bad practice?.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 19 '18 at 5:51









    Kusalananda

    122k16230375




    122k16230375












    • I edited the question with way more detail and sample runs. As you indicated Kusalananda, its apart of a larger loop. The use of awk is definitely an option, but I'd like to see if the collective can figure out the underlying behaviour of how BASH is working towards processing the expression.
      – AfroJoe
      Sep 19 '18 at 13:09


















    • I edited the question with way more detail and sample runs. As you indicated Kusalananda, its apart of a larger loop. The use of awk is definitely an option, but I'd like to see if the collective can figure out the underlying behaviour of how BASH is working towards processing the expression.
      – AfroJoe
      Sep 19 '18 at 13:09
















    I edited the question with way more detail and sample runs. As you indicated Kusalananda, its apart of a larger loop. The use of awk is definitely an option, but I'd like to see if the collective can figure out the underlying behaviour of how BASH is working towards processing the expression.
    – AfroJoe
    Sep 19 '18 at 13:09




    I edited the question with way more detail and sample runs. As you indicated Kusalananda, its apart of a larger loop. The use of awk is definitely an option, but I'd like to see if the collective can figure out the underlying behaviour of how BASH is working towards processing the expression.
    – AfroJoe
    Sep 19 '18 at 13:09













    0














    I suspect you want:



    if [[ $line = *RAW_READ_ERROR_RATE* || 
    $line = READ:* && $line != *"READ: DISABLED"* ]]; then


    The && [[...]] operator has precedence over || but the && shell operator has same precedence as ||.



    Or to make it explicit:



    if [[ $line = *RAW_READ_ERROR_RATE* || 
    ($line = READ:* && $line != *"READ: DISABLED"*) ]]; then


    Or using the &&/|| shell operators and multiple [[...]]s:



    if [[ $line = *RAW_READ_ERROR_RATE* ]] || { 
    [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]]; }; then


    Or change the order:



    if [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]] ||
    [[ $line = *RAW_READ_ERROR_RATE* ]]; then


    Or use a pattern that matches all:



    if [[ $line = @(*RAW_READ_ERROR_RATE*|!(!(*READ:*)|*READ: DISABLED*)) ]]; then


    Without the parenthesis/braces, yours is read as:



    if [[ ($line = *RAW_READ_ERROR_RATE* || 
    $line = READ:*) && $line != *"READ: DISABLED"* ]]; then


    That shouldn't prevent it from matching lines that contain RAW_READ_ERROR_RATE though provided they don't contain READ: DISABLED.






    share|improve this answer




























      0














      I suspect you want:



      if [[ $line = *RAW_READ_ERROR_RATE* || 
      $line = READ:* && $line != *"READ: DISABLED"* ]]; then


      The && [[...]] operator has precedence over || but the && shell operator has same precedence as ||.



      Or to make it explicit:



      if [[ $line = *RAW_READ_ERROR_RATE* || 
      ($line = READ:* && $line != *"READ: DISABLED"*) ]]; then


      Or using the &&/|| shell operators and multiple [[...]]s:



      if [[ $line = *RAW_READ_ERROR_RATE* ]] || { 
      [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]]; }; then


      Or change the order:



      if [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]] ||
      [[ $line = *RAW_READ_ERROR_RATE* ]]; then


      Or use a pattern that matches all:



      if [[ $line = @(*RAW_READ_ERROR_RATE*|!(!(*READ:*)|*READ: DISABLED*)) ]]; then


      Without the parenthesis/braces, yours is read as:



      if [[ ($line = *RAW_READ_ERROR_RATE* || 
      $line = READ:*) && $line != *"READ: DISABLED"* ]]; then


      That shouldn't prevent it from matching lines that contain RAW_READ_ERROR_RATE though provided they don't contain READ: DISABLED.






      share|improve this answer


























        0












        0








        0






        I suspect you want:



        if [[ $line = *RAW_READ_ERROR_RATE* || 
        $line = READ:* && $line != *"READ: DISABLED"* ]]; then


        The && [[...]] operator has precedence over || but the && shell operator has same precedence as ||.



        Or to make it explicit:



        if [[ $line = *RAW_READ_ERROR_RATE* || 
        ($line = READ:* && $line != *"READ: DISABLED"*) ]]; then


        Or using the &&/|| shell operators and multiple [[...]]s:



        if [[ $line = *RAW_READ_ERROR_RATE* ]] || { 
        [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]]; }; then


        Or change the order:



        if [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]] ||
        [[ $line = *RAW_READ_ERROR_RATE* ]]; then


        Or use a pattern that matches all:



        if [[ $line = @(*RAW_READ_ERROR_RATE*|!(!(*READ:*)|*READ: DISABLED*)) ]]; then


        Without the parenthesis/braces, yours is read as:



        if [[ ($line = *RAW_READ_ERROR_RATE* || 
        $line = READ:*) && $line != *"READ: DISABLED"* ]]; then


        That shouldn't prevent it from matching lines that contain RAW_READ_ERROR_RATE though provided they don't contain READ: DISABLED.






        share|improve this answer














        I suspect you want:



        if [[ $line = *RAW_READ_ERROR_RATE* || 
        $line = READ:* && $line != *"READ: DISABLED"* ]]; then


        The && [[...]] operator has precedence over || but the && shell operator has same precedence as ||.



        Or to make it explicit:



        if [[ $line = *RAW_READ_ERROR_RATE* || 
        ($line = READ:* && $line != *"READ: DISABLED"*) ]]; then


        Or using the &&/|| shell operators and multiple [[...]]s:



        if [[ $line = *RAW_READ_ERROR_RATE* ]] || { 
        [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]]; }; then


        Or change the order:



        if [[ $line = READ:* ]] && [[ $line != *"READ: DISABLED"* ]] ||
        [[ $line = *RAW_READ_ERROR_RATE* ]]; then


        Or use a pattern that matches all:



        if [[ $line = @(*RAW_READ_ERROR_RATE*|!(!(*READ:*)|*READ: DISABLED*)) ]]; then


        Without the parenthesis/braces, yours is read as:



        if [[ ($line = *RAW_READ_ERROR_RATE* || 
        $line = READ:*) && $line != *"READ: DISABLED"* ]]; then


        That shouldn't prevent it from matching lines that contain RAW_READ_ERROR_RATE though provided they don't contain READ: DISABLED.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Sep 19 '18 at 14:58

























        answered Sep 19 '18 at 13:15









        Stéphane Chazelas

        300k54564913




        300k54564913






























            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.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • 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%2f469914%2fcolon-character-is-messing-up-my-pattern-match-in-bash%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            濃尾地震

            How to rewrite equation of hyperbola in standard form

            No ethernet ip address in my vocore2