grepping a variable and adding 1 to it

7,097

Solution 1

You're using the wrong quotes: single quotes '' prevent expansion of $ expressions ($var and $(command), and the legacy `command` form). Use double quotes "" instead. Although in this case, if you're certain that it's a number then you don't need any quotes.

For your second question... are you using leading zeroes? That indicates octal, so the digits 8 and 9 won't work.

Solution 2

geekosaur has already explained why your first attempt failed. Here are some additional tips on what you're trying to do.

If you're looking for a number like 42, you probably want to match 042 but not 1042 or 421. All you need to achieve that is a fancier regular expression. Assuming $newnumber contains the number (integer, positive, in decimal notation) with no leading zero, look for $newnumber preceded by either the beginning of the line or a non-digit character, and likewise after. 0* further allows leading zeroes. The -E option tells grep that you're using the modern regular expression syntax (as opposed to the historical syntax, which is quirkier and less powerful).

grep -E "(^|[^0-9])0*$newnumber(\$|^[0-9])" /path/to/file

To parse a number with potential leading zeroes, in bash, you can use $((10#$newnumber)) to force a decimal interpretation. In other shells, it's a little more complicated; there's a shell construct to get the value of a variable without a particular prefix ${var#prefix}, and a similar construct for suffixes ${var%suffix}, but there's no way to specify “the longest possible sequence of 0 characters” as a prefix to strip. But it can be done in two steps: first obtain the part of var that isn't the leading zeroes, and use that as a prefix to strip. The part of var that isn't the leading zeros is its longest suffix that begins with a non-zero, which is ${var%%[!0]*} (the double % means to take out the longest suffix that matches the pattern; a single % would take out the shortest suffix).

read number
number=${number#${number%%[!0]*}}

Further note: grep REGEXP /some/file searches the one file /some/file. If you want to search all the files in a directory, let the shell generate the list of files: grep REGEXP /some/dir/*. If you want to search all the files in a directory and its subdirectories recursively, pass the -r option to grep to make it recurse: grep -r REGEXP /some/dir.

Share:
7,097
afbr1201
Author by

afbr1201

Updated on September 18, 2022

Comments

  • afbr1201
    afbr1201 almost 2 years

    I have a variable containing a leading zeroes number, and I want to grep this variable and that same variable plus one. I made several attempts but ran into errors. Here's what I want to do:

    read var
    newvar=$(($var +1))
    grep '$var' /some/dir
    grep '$newvar' /some/dir
    

    I really think there's something wrong with my code. I also tried some test like this:

    #!/bin/bash
    echo "enter number"
    read number
    newnumber=$(($number + 1))
    echo "$newnumber"
    

    That gives me an error: value too great for base (error token is. If i do it like this:

     #!/bin/bash
    echo "enter number"
    read number
    number=""
    newnumber=$(($number + 1))
    echo "$newnumber"
    

    This will output 1 all the time.

    What's wrong with my attempts, and how can I do what I want?

    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' almost 13 years
      ​@user774187 Please don't edit away a whole chunk of your question, as it causes some of the answers to stop making sense.
    • afbr1201
      afbr1201 almost 13 years
      noted on that @Gilles and thanks for the help.
  • afbr1201
    afbr1201 almost 13 years
    yes, i am leading zeros, i need to grep a certain line with zeroes but the format of it was 01,02,03 so on so i need to grep like 03-04 but i think its not working.
  • geekosaur
    geekosaur almost 13 years
    If you need to do that, you need to omit the leading zeroes for the math part and then use printf to reformat with the leading zero. Or you can try using 10#$number to see if it will force base 10.
  • Karu
    Karu almost 13 years
    Nice catch on the octal thing. The question needs to be restated if he's actually wanting to increment a string with a leading 0.
  • afbr1201
    afbr1201 almost 13 years
    @mark, thanks for the suggestion, @geekosaur -- yes i am trying to grep something with leading zeroes,, and appending 10# did work, now i just have to do it the harder way.. haha, thanks guys!
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 13 years
    Assuming number contains a bunch of digits, $((number+1)) is exactly equivalent to $(($number)). Parameter substitution is performed within arithmetic expressions.
  • Karu
    Karu almost 13 years
    It is still a bad habit to get into and shows a fundamental misunderstanding of the $((...)) construct. Let him try $(($number+=50,$number/2)) someday and see what he gets.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 13 years
    That's obviously broken (if $number contains digits): you don't write $foo=bar for an assignment in the shell. (But actually $(($x+=50)) can make sense, if $x is the name of another variable!) (Of course I meant $((number+1)) is equivalent to $(($number+1)) above.)
  • afbr1201
    afbr1201 almost 13 years
    hi i tried that line but it would give me an error token value is too great for base enter number 09 a: line 4: 09: value too great for base (error token is "09")
  • Karu
    Karu almost 13 years
    Yeah, user774187, the octal thing that geekosaur pointed out is going to bite you when printf runs. You'd need printf -v newvar "%02d" "10#$newvar" to avoid that issue.
  • afbr1201
    afbr1201 almost 13 years
    this line worked fine number=${number#${number%%[!0]*}} the problem now it i want to force a 0 on the output as well to make it a 2 digit number, E.G. 01-09 but not 010-099. any suggestion?
  • afbr1201
    afbr1201 almost 13 years
    same thing happened @Mark, #!/bin/bash echo "enter number" read var newvar=$((var + 1)) printf -v newvar "%02d" "10#$newvar" output enter number 09 a: line 6: 09: value too great for base (error token is "09")
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' almost 13 years
    A simple solution is to use printf: printf %02d "$number", or printf '%02d\n' "$number" if you want to add a newline.
  • Karu
    Karu almost 13 years
    I thought you only needed help with printf from me. Sorry. I'll edit my answer further.
  • afbr1201
    afbr1201 almost 13 years
    i wanted to try various ways, but that printf wont work for me yet.. and i really appreciate you guys helping me out,.. i am still a newbie on bash..
  • Admin
    Admin about 2 years
    (1) The bit about “grep” is an incandescent red herring. The OP explicitly said that they want to grep for number and newnumber in /some/dir, but it wasn’t a critical part of the question. It’s OK that you didn’t bother regurgitating it, but to claim that your answer is somehow more streamlined than the others is just bragging about how you did half of the job using half as much time. (2) The trick with 10000 does not work. (3) Even if it did, you should explain how it works.