public inbox for gentoo-user@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-user] bash script question
@ 2014-08-18  8:54 Adam Carter
  2014-08-18  9:42 ` wraeth
  0 siblings, 1 reply; 9+ messages in thread
From: Adam Carter @ 2014-08-18  8:54 UTC (permalink / raw
  To: gentoo-user@lists.gentoo.org

[-- Attachment #1: Type: text/plain, Size: 497 bytes --]

I want to use an if/then that tests for the existence of a string in 4
files. Usually I do this by checking the exit code of grep, when i'm
checking a single file. However, I cant get the syntax right for multiple
checks.



To troubleshoot I’ve dropped back to just checking two files, and i’ve
tried things like



If [ $(grep blah file1.txt) –a $(grep blah file2.txt) ]; then



But this matches if grep fails both times as well as when it matches both
time. Any ideas?

[-- Attachment #2: Type: text/html, Size: 715 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18  8:54 [gentoo-user] bash script question Adam Carter
@ 2014-08-18  9:42 ` wraeth
  2014-08-18 11:29   ` Stroller
  0 siblings, 1 reply; 9+ messages in thread
From: wraeth @ 2014-08-18  9:42 UTC (permalink / raw
  To: gentoo-user

[-- Attachment #1: Type: text/plain, Size: 426 bytes --]

On Mon, 2014-08-18 at 18:54 +1000, Adam Carter wrote:
> But this matches if grep fails both times as well as when it matches both
> time. Any ideas?

If you don't mind using a quick loop, you could use something like:

n=0
for f in file1.txt file2.txt file3.txt file4.txt; do
    grep 'string' ${f} >> /dev/null && n=$[n+1]
done

if [[ $n == 4 ]]; then
    do_something
fi


-- 
wraeth <wraeth@wraeth.id.au>

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18  9:42 ` wraeth
@ 2014-08-18 11:29   ` Stroller
  2014-08-18 11:58     ` wraeth
  2014-08-18 12:16     ` Kerin Millar
  0 siblings, 2 replies; 9+ messages in thread
From: Stroller @ 2014-08-18 11:29 UTC (permalink / raw
  To: gentoo-user


On Mon, 18 August 2014, at 10:42 am, wraeth <wraeth@wraeth.id.au> wrote:

> On Mon, 2014-08-18 at 18:54 +1000, Adam Carter wrote:
>> But this matches if grep fails both times as well as when it matches both
>> time. Any ideas?
> 
> If you don't mind using a quick loop, you could use something like:
> 
> n=0
> for f in file1.txt file2.txt file3.txt file4.txt; do
>    grep 'string' ${f} >> /dev/null && n=$[n+1]
> done
> 
> if [[ $n == 4 ]]; then
>    do_something
> fi

I've solved similar problems the same way myself, but I hope you'll forgive me for offering unsolicited critique on a small detail.

In the above 4 is a constant, and thus it's independent of the number of files being tested.

I propose addressing this with an array of the filenames.

Thus additional files can be added for testing, without manual adjustment of the expected total.

  files=("file1.txt" "file2.txt" "file3.txt" "file4.txt")
  n=0
  for f in ${files[@]}; do
     grep 'string' ${f} >> /dev/null && n=$[n+1]
  done

  if [[ $n == ${#files[@]} ]]; then
     do_something
  fi

Bash array syntax is a bit arcane, but at least these very useful data structures are available.

Stroller.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18 11:29   ` Stroller
@ 2014-08-18 11:58     ` wraeth
  2014-08-18 13:53       ` Stroller
  2014-08-18 12:16     ` Kerin Millar
  1 sibling, 1 reply; 9+ messages in thread
From: wraeth @ 2014-08-18 11:58 UTC (permalink / raw
  To: gentoo-user

[-- Attachment #1: Type: text/plain, Size: 670 bytes --]

On Mon, 2014-08-18 at 12:29 +0100, Stroller wrote:
> On Mon, 18 August 2014, at 10:42 am, wraeth <wraeth@wraeth.id.au> wrote:
> I propose addressing this with an array of the filenames.
> 
> Thus additional files can be added for testing, without manual adjustment of the expected total.

+1

I considered scalability as I was writing this, however I've never been
overly familiar with bash arrays (I tend towards python or perl if I
need anything even starting to get complex); and my method, while
slightly more manual, solved the stated problem.

That being said, your solution is a much more elegant spin on it. :)

-- 
wraeth <wraeth@wraeth.id.au>

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 213 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18 11:29   ` Stroller
  2014-08-18 11:58     ` wraeth
@ 2014-08-18 12:16     ` Kerin Millar
  2014-08-18 14:02       ` Stroller
  1 sibling, 1 reply; 9+ messages in thread
From: Kerin Millar @ 2014-08-18 12:16 UTC (permalink / raw
  To: gentoo-user

On 18/08/2014 12:29, Stroller wrote:
>
> On Mon, 18 August 2014, at 10:42 am, wraeth <wraeth@wraeth.id.au> wrote:
>
>> On Mon, 2014-08-18 at 18:54 +1000, Adam Carter wrote:
>>> But this matches if grep fails both times as well as when it matches both
>>> time. Any ideas?
>>
>> If you don't mind using a quick loop, you could use something like:
>>
>> n=0
>> for f in file1.txt file2.txt file3.txt file4.txt; do
>>     grep 'string' ${f} >> /dev/null && n=$[n+1]
>> done
>>
>> if [[ $n == 4 ]]; then
>>     do_something
>> fi
>
> I've solved similar problems the same way myself, but I hope you'll forgive me for offering unsolicited critique on a small detail.
>
> In the above 4 is a constant, and thus it's independent of the number of files being tested.
>
> I propose addressing this with an array of the filenames.
>
> Thus additional files can be added for testing, without manual adjustment of the expected total.
>
>    files=("file1.txt" "file2.txt" "file3.txt" "file4.txt")
>    n=0
>    for f in ${files[@]}; do
>       grep 'string' ${f} >> /dev/null && n=$[n+1]

I would write `grep -q -m1 -F 'string' ...` here. In particular, -m1 
will short-circuit after finding one match.

>    done
>
>    if [[ $n == ${#files[@]} ]]; then
>       do_something
>    fi
>
> Bash array syntax is a bit arcane, but at least these very useful data structures are available.

Here's a slightly different take. It avoids multiple grep invocations, 
which could be a good thing in the case of a lengthy file list.

     files=(file1.txt file2.txt file3.txt file4.txt)
     string="matchme" # Using -F below as it's a string, not a regex

     count=0
     while read -r matches; do
         (( count += matches ))
     done < <(grep -hcm1 -F "$string" ${files[*]})

     if (( count == ${#files[@]} )); then
         do_something
     fi

--Kerin



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18 11:58     ` wraeth
@ 2014-08-18 13:53       ` Stroller
  0 siblings, 0 replies; 9+ messages in thread
From: Stroller @ 2014-08-18 13:53 UTC (permalink / raw
  To: gentoo-user


On Mon, 18 August 2014, at 12:58 pm, wraeth <wraeth@wraeth.id.au> wrote:
> ... I've never been
> overly familiar with bash arrays (I tend towards python or perl if I
> need anything even starting to get complex);

Indeed, I had to look up the syntax from my own snippets folder, myself.

I need to exercise my Perl - I like it very much, from the little I've done.

> and my method, while
> slightly more manual, solved the stated problem.

And illustrated the solution very clearly, too. :)

> That being said, your solution is a much more elegant spin on it. :)

Thank you. It's what I strive for.

Stroller.




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18 12:16     ` Kerin Millar
@ 2014-08-18 14:02       ` Stroller
  2014-08-18 14:18         ` Kerin Millar
  0 siblings, 1 reply; 9+ messages in thread
From: Stroller @ 2014-08-18 14:02 UTC (permalink / raw
  To: gentoo-user


On Mon, 18 August 2014, at 1:16 pm, Kerin Millar <kerframil@fastmail.co.uk> wrote:
...
>        (( count += matches ))
>    done < <(grep -hcm1 -F "$string" ${files[*]})

Oh, this is lovely.

I've learned some things today.

>    if (( count == ${#files[@]} )); then

May I ask why you prefer these brackets for evaluation, please?

Stroller.




^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18 14:02       ` Stroller
@ 2014-08-18 14:18         ` Kerin Millar
  2014-08-18 14:28           ` Kerin Millar
  0 siblings, 1 reply; 9+ messages in thread
From: Kerin Millar @ 2014-08-18 14:18 UTC (permalink / raw
  To: gentoo-user

On 18/08/2014 15:02, Stroller wrote:
>
> On Mon, 18 August 2014, at 1:16 pm, Kerin Millar <kerframil@fastmail.co.uk> wrote:
> ...
>>         (( count += matches ))
>>     done < <(grep -hcm1 -F "$string" ${files[*]})
>
> Oh, this is lovely.
>
> I've learned some things today.
>
>>     if (( count == ${#files[@]} )); then
>
> May I ask why you prefer these brackets for evaluation, please?

There was no particular reason, other than to maintain consistency in 
the example (both for evaluation and as an alternative to expansion). 
Sometimes, I find double square brackets to be a bit of an eyesore, but 
do tend to use them more often than not.

I particularly like double parentheses for checking exit codes assigned 
to variables. For example:

(( $? )) && echo "something went wrong"

As opposed to having to perform an explicit comparison:

[[ $? != 0 ]] && echo "something went wrong"

--Kerin


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [gentoo-user] bash script question
  2014-08-18 14:18         ` Kerin Millar
@ 2014-08-18 14:28           ` Kerin Millar
  0 siblings, 0 replies; 9+ messages in thread
From: Kerin Millar @ 2014-08-18 14:28 UTC (permalink / raw
  To: gentoo-user

On 18/08/2014 15:18, Kerin Millar wrote:
> On 18/08/2014 15:02, Stroller wrote:
>>
>> On Mon, 18 August 2014, at 1:16 pm, Kerin Millar
>> <kerframil@fastmail.co.uk> wrote:
>> ...
>>>         (( count += matches ))
>>>     done < <(grep -hcm1 -F "$string" ${files[*]})
>>
>> Oh, this is lovely.
>>
>> I've learned some things today.
>>
>>>     if (( count == ${#files[@]} )); then
>>
>> May I ask why you prefer these brackets for evaluation, please?
>
> There was no particular reason, other than to maintain consistency in
> the example (both for evaluation and as an alternative to expansion).
> Sometimes, I find double square brackets to be a bit of an eyesore, but
> do tend to use them more often than not.
>
> I particularly like double parentheses for checking exit codes assigned
> to variables. For example:
>
> (( $? )) && echo "something went wrong"
>
> As opposed to having to perform an explicit comparison:
>
> [[ $? != 0 ]] && echo "something went wrong"

Oops, I meant to use the -ne operator there. Not that it actually makes 
a difference for this test.

--Kerin


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-08-18 14:28 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-18  8:54 [gentoo-user] bash script question Adam Carter
2014-08-18  9:42 ` wraeth
2014-08-18 11:29   ` Stroller
2014-08-18 11:58     ` wraeth
2014-08-18 13:53       ` Stroller
2014-08-18 12:16     ` Kerin Millar
2014-08-18 14:02       ` Stroller
2014-08-18 14:18         ` Kerin Millar
2014-08-18 14:28           ` Kerin Millar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox