Find the answer to your Linux question:
Results 1 to 10 of 10
Is there a way to incorporate awk as an "if" test-command? As a basic example: I need to find a line that contains peanuts, elephant and clowns, such as this ...
  1. #1
    Just Joined!
    Join Date
    Jan 2010
    Posts
    12

    Using awk for an IF test?

    Is there a way to incorporate awk as an "if" test-command?

    As a basic example:

    I need to find a line that contains peanuts, elephant and clowns, such as this line:

    awk '/peanuts.*elephant.*clown/' events.txt

    If the file does contain a line with all three words I'm going to echo "The circus is in town"

    If there is not a matching line than I need to

    awk '/Talladega.*NASCAR.*Cup/' events.txt

    and if that exists I will echo "There's a race this weekend!"

    If it does not exist I wantt to just echo something and kill the script.

    I have no problem with the if, then and else part of it. I just can't seem to come up with the correct syntax to use awk as a test on if.

  2. #2
    Linux User
    Join Date
    Nov 2009
    Location
    France
    Posts
    292
    Code:
    if [ -n "$(awk '/pattern/' file)" ]

  3. #3
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    So this can be done with awk. The problem is that awk is a complicated tool with fun syntax, the ability to modify lines, and deal well with fields. You may notice that most of these are not what you need.

    There is a much simpler tool that will be easier for you.

    The tool "grep" takes a bunch of input and looks for a specific pattern inside of it. This is exactly what you need.

    In your particular case, you could do this:
    Code:
    if grep -q 'peanuts.*elephant.*clown' events.txt; then
        echo "The circus is in town!"
    elif grep -q 'Talladega.*Nascar.*Cup' events.txt; then
        echo "There's a race this weekend!"
    else
        echo "There are no events.  Sorry."
    fi
    In this syntax, grep takes a pattern and a text file and searches for a line containing the requested pattern. Normally, grep would then print out that line.

    However, by using the "-q" option (which was built specifically for this purpose), we tell grep to not print anything, and instead simply notify us if a match was found. This allows for simple constructions like the above.

    I hope this helps you out.
    DISTRO=Arch
    Registered Linux User #388732

  4. #4
    Just Joined!
    Join Date
    Jan 2010
    Posts
    12
    Quote Originally Posted by nmset View Post
    Code:
    if [ -n "$(awk '/pattern/' file)" ]
    This works okay nmset. Actually I was stumbling all over this on my own. Close but no cigar. I eventually discovered some errors in my patterns and some quote marks misplaced.

    I do have one question. I note you are using -n here. Strange as it seems, my list of "primaries" that I obtained from the net does not have this. It does have a -N

    I googled a bit and it seems -n tests to see if the argument is non empty. I just found it unique that my laundry list has -f -d -k -p -r, etc. but no -n so, I added it.

  5. #5
    Just Joined!
    Join Date
    Jan 2010
    Posts
    12
    Quote Originally Posted by Cabhan View Post
    So this can be done with awk. The problem is that awk is a complicated tool with fun syntax, the ability to modify lines, and deal well with fields. You may notice that most of these are not what you need.

    There is a much simpler tool that will be easier for you.
    Thanks for the info Cabhan and the grep suggestion. I will test your code later this evening.

    I do see what you mean about it being much simpler and less aggravating to construct.

    Do I assume here that with these patterns grep will come up true if it finds elephant, elephant47, 45elephant89 if any exist? If so, is there a way to force grep to just key in on elephant and nothing more. Brackets like used in a range maybe?

  6. #6
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    So in your original awk statement, you used a pattern which I used as well in my grep example. These patterns are called regular expressions. Regular expressions tend to work the same across all utilities that use regular expressions, so the behaviour of a match in awk should be the same as a behaviour as a match in grep.

    In the pattern /peanuts.*elephant.*clown/, the ".*" bits mean 0 or more of any characters. You could also read ".*" as "some amount of anything". So this regular expression matches any of the following:
    Code:
    peanutselephantclown
    peanuts LA LA LA LOOK AT ME elephant WOULDN'T YOU LIKE A clown
    There will be peanuts, an elephant, and a clown
    ...
    If you want to check for a line that contains only the word "elephant", you could use a regular expression such as /^elephant$/. "^" means the beginning of the line and "$" means the end of the line. Therefore, this looks for a line that is simply "elephant".

    Did I understand your question correctly? Does this help?
    DISTRO=Arch
    Registered Linux User #388732

  7. #7
    Linux User
    Join Date
    Nov 2009
    Location
    France
    Posts
    292
    I do have one question
    [ -n $SOMEVAR ] is a test on a variable. You could also write

    Code:
    test -n $SOMEVAR
    without square brackets.

    Code:
    man test
    for all available tests. The test utility is intended to be used with single or multiple variables, or with files.

    But, as fo awk usage, using grep would be simpler in this case.

  8. #8
    Just Joined!
    Join Date
    Jan 2010
    Posts
    12
    Quote Originally Posted by Cabhan View Post

    If you want to check for a line that contains only the word "elephant", you could use a regular expression such as /^elephant$/. "^" means the beginning of the line and "$" means the end of the line. Therefore, this looks for a line that is simply "elephant".

    Did I understand your question correctly? Does this help?
    I'm not totally sure if you did fully but you did hit upon some of what I am getting at. I understand we are dealing with patters here. A search for car will find car, cargo, boxcar, etc. and I get your jest concerning the /^elephant$/ but what happens if I need to find a line that contains elephant, peanut and clown and no derivatives such as peanuts, elephantiasis, clowned, etc. Is there something I can use for start and end of word in the same manner one can limit end and/or start of line?

  9. #9
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    Ah, I see what you mean, and the answer is "it depends on the tool". I know that I said regexes are generally the same everywhere, but that technically isn't true.

    There are a few regex standards. The first is POSIX regexes, which are what awk, sed, grep, etc. use by default. These are fairly basic. You then have Extended Regular Expressions, which add some additional features. You then have non-standard ones, such as Perl regular expressions. These add additional features that are very helpful, but which may not be recognized everywhere.

    grep, for instance, recognizes the \< and \> anchors, which mean the beginning and the end of a word respectively. So the regular expression /\<elephant\>/ will match the following lines:
    Code:
    elephant
    There is an elephant.
    I want an elephant, but they are expensive.
    However, it will *not* match the following:
    Code:
    elephants
    32elephant.
    This feature is also recognized in vim, for instance. Perl uses \b to mean a word boundary (grep recognizes this as well, but \< and \> are a bit more specific).

    Note that a "word" in this case is generally recognized as the regular expression /[0-9A-Za-z_]+/, though grep might use /[0-9A-Za-z]+/ instead.

    Does this help?
    DISTRO=Arch
    Registered Linux User #388732

  10. #10
    Just Joined!
    Join Date
    Jan 2010
    Posts
    12
    Quote Originally Posted by Cabhan View Post
    grep, for instance, recognizes the \< and \> anchors, which mean the beginning and the end of a word respectively. So the regular expression /\<elephant\>/ will match the following lines:
    Code:
    elephant
    There is an elephant.
    I want an elephant, but they are expensive.
    However, it will *not* match the following:
    Code:
    elephants
    32elephant.
    This feature is also recognized in vim, for instance. Perl uses \b to mean a word boundary (grep recognizes this as well, but \< and \> are a bit more specific).

    Note that a "word" in this case is generally recognized as the regular expression /[0-9A-Za-z_]+/, though grep might use /[0-9A-Za-z]+/ instead.

    Does this help?
    Yes Cabhan, this does help very much and is what I was specifically after. What I am scripting alters a user's configuration file and it needs to be precise and totally accurate.

    I appreciate all the information you've provided and also appreciate the time you've taken to explain this with a bit more depth.

    Speed

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...