LinuxN00b
LinuxN00b

Reputation: 33

Bash script - Adding/Subtracting 1 from file

This is what I'm trying to do:

I want to make a script that i can invoke either with counter_use in or counter_use out. If i type in i want a counter to add +1 to the numeric value inside a file called "counter", if I type out i want to subtract 1 from the file.

I also want the script to output Logged in if the value in counter are equal to or higher than 1 and Not logged in if the counter is equal to 0.

The last part is runnig if i hard code the counter to a specific number. The problem is the first part.

echo "In or out?"

read input > counterFile

if grep -q "in" counterFile
    then //what should I do here so that it adds +1 to a file called 
counter?

elif grep -q "out" counterFile
    then //what should I do here so that it subtracts -1 to a file called 
counter?

if [ $counter -ge 1 ]
    then
        echo "Logged in"

elif [ $counter -eq 0 ]
    then
        echo "Not logged in"

else
        echo "Wrong input"

fi

Upvotes: 1

Views: 652

Answers (3)

ralf htp
ralf htp

Reputation: 9422

#!/bin/bash


echo "In or out?"

read c <&0  # reads from stdin file descriptor &0 is stdin

if [[ $c == 'In' ]] || [[ $c == 'in' ]];  
then
counter=$(<counter.txt) # reads counter from file
let "counter = counter +1"  # increases variable
echo "$counter" > 'counter.txt' # write new value to file overwriting the old
elif [[ $c == 'Out' ]] || [[ $c == 'out' ]];
then
counter=$(<counter.txt) # reads from file
let "counter = counter -1"
#echo "$counter" > 'counter.txt'
else
echo "wrong input..."
fi

Write to file, but overwrite it if it exists

https://askubuntu.com/questions/385528/how-to-increment-a-variable-in-bash/706683

http://ryanstutorials.net/bash-scripting-tutorial/bash-if-statements.php

Upvotes: 0

mklement0
mklement0

Reputation: 437109

romaric crailox's helpful answer contains many useful pointers, but the code can be streamlined to become a more idiomatic (Bash) solution:

#!/bin/bash

# Create the counter file on demand.
[[ -f counter ]] || echo 0 > counter

# Prompt until valid input is received.
while read -p 'In or out? ' input; do

  case $input in
    'in')
      # Update the counter file by incrementing the number it contains.
      perl -i -ple '++$_' counter
      break # valid input received, exit the loop
      ;;
    'out')
      # Update the counter file by decrementing the number it contains.
      perl -i -ple '--$_' counter
      break # valid input received, exit the loop
      ;;
    *)
      echo "Invalid input." >&2  # echo error to *stderr*
      # Stay in the loop to prompt again.
      ;;    
  esac

done

# Read the updated counter file and echo the implied status.
counter=$(< counter)
if (( counter >= 1 )); then
  echo 'Logged in.'
elif (( counter == 0 )); then
  echo 'Not logged in.'
else
  echo "Invalid state: counter is $counter" >&2
fi

Note:

  • The use of case ... esac to handle multiple conditions more succinctly than an if ... elif ... fi statement.

  • Outputting error messages to stderr with >&2

  • Use of a perl command to update file counter in place:

    • -i activates in-place updating
    • -ple automatically prints the (modified) input line, -l adds intelligent newline handing, and -e specifies the expression (script) to run (the following argument)
    • ++$_ / --$_ then simply increments / decrements the input line at hand ($_), which, thanks to -p, gets output automatically, and, thanks to -i, written back to the original file (loosely speaking; a new file is created that replaces the original).
  • Use of arithmetic evaluation ((( ... ))) to test numbers.

Upvotes: 2

romaric crailox
romaric crailox

Reputation: 584

First problem is the use of read command. Try this

read -p "in or out ?" input
  • -p option is to specifie something to print to stdout
  • input is the name of shell script variable that will store user input

After this command, input variable will be in or out. Then you can test if input is in or out with an if expression :

if [ "$input" == "in" ] [...]

To add or substract 1 to value inside counter file, you can retrieve current value Inside file, add or substract 1 and write new value Inside file (I'm not sure you want to write new value. Try this :

crt_val=$(cat ./counter)
new_val=$(( crt_val + 1 ))
echo $new_val > ./counter

Counter file have to be present, so you can add, at the beginning of script

if [ -e ./counter ] ; then echo "0" > ./counter ; fi

Finally, code can be this :

# user entry
read -p "in or out ? " input

# initialize counter file
if [ ! -e ./counter ] ; then echo "0" > ./counter ; fi

# Doing what user entry ask to do
if [ "$input" == "in" ]
then
  echo "in"
  crt_val=$(cat ./counter)
  new_val=$(( crt_val + 1 ))
  echo $new_val > ./counter
elif [ "$input" == "out" ]
then
  echo "out"
  crt_val=$(cat ./counter)
  new_val=$(( crt_val - 1 ))
  echo $new_val > ./counter
else
  echo "Wrong input, try in or out"
  exit 1
fi

# Output
if [ $new_val -ge 1 ]
then
  echo "Logged in"
elif [ $new_val -eq 0 ]
then
  echo "Not logged in"
else
  echo "Wrong counter value"
fi

Be carefull, user entry have to be exactly in or out (case sensitive), and have to be no empty. To protect empty answer, try if [ "x$input" == "xin" ] [...]

Hope this help

Upvotes: 1

Related Questions