1

I am looking to search for strings within a file using variables.

I have a script that will accept 3 or 4 parameters: 3 are required; the 4th isn't mandatory.

I would like to search the text file for the 3 parameters matching within the same line, and if they do match then I want to remove that line and replace it with my new one - basically it would update the 4th parameter if set, and avoid duplicate entries.

Currently this is what I have:

input=$(egrep -e '$domain\s+$type\s+$item' ~/etc/security/limits.conf)

if [ "$input" == "" ]; then

    echo $domain $type $item $value >>~/etc/security/limits.conf

    echo \"$domain\" \"$type\" \"$item\" \"$value\" has been successfully added to your limits.conf file.


else
    cat ~/etc/security/limits.conf | egrep -v "$domain|$type|$item" >~/etc/security/limits.conf1
    rm -rf ~/etc/security/limits.conf
    mv ~/etc/security/limits.conf1 ~/etc/security/limits.conf

    echo $domain    $type    $item   $value >>~/etc/security/limits.conf

    echo \"$domain\" \"$type\" \"$item\" \"$value\" has been successfully added to your limits.conf file.
    exit 0
fi

Now I already know that the input=egrep etc.. will not work; it works if I hard code some values, but it won't accept those variables. Basically I have domain=$1, type=$2 and so on.

I would like it so that if all 3 variables are not matched within one line, than it will just append the parameters to the end of the file, but if the parameters do match, then I want them to be deleted, and appended to the file. I know I can use other things like sed and awk, but I have yet to learn them.

This is for a school assignment, and all help is very much appreciated, but I'd also like to learn why and how it works/doesn't, so if you can provide answers to that as well that would be great!

3 Answers 3

2

Three things:

  • To assign the output of a command, use var=$(cmd).
  • Don't put spaces around the = in assignments.
  • Expressions don't expand in single quotes: use double quotes.

To summarize:

input=$(egrep -e "$domain\s+$type\s+$item" ~/etc/security/limits.conf)

Also note that ~ is your home directory, so if you meant /etc/security/limits.conf and not /home/youruser/etc/security/limits.conf, leave off the ~

Sign up to request clarification or add additional context in comments.

2 Comments

I'm a ksh guy myself - we would use `yourexpression` to do this. Does that work in bash as well or only $( )?
Both backticks and $(..) works in all POSIX shells including bash and ksh. $(..) is much better though; it nests better and has less surprising escape behavior.
0

You have several bugs in your script. Here's your script with some comments added

input=$(egrep -e '$domain\s+$type\s+$item' ~/etc/security/limits.conf)
     # use " not ' in the string above or the shell can't expand your variables.
     # some versions of egrep won't understand '\s'. The safer, POSIX character class is [[:blank:]].

if [ "$input" == "" ]; then
     # the shell equality test operator is =, not ==. Some shells will also take == but don't count on it.
     # the normal way to check for a variable being empty in shell is with `-z`
     # you can have problems with tests in some shells if $input is empty, in which case you'd use [ "X$input" = "X" ].

    echo $domain $type $item $value >>~/etc/security/limits.conf
    # echo is unsafe and non-portable, you should use printf instead.
    # the above calls echo with 4 args, one for each variable - you probably don't want that and should have double-quoted the whole thing.
    # always double-quote your shell variables to avoid word splitting ad file name expansion (google those - you don't want them happening here!)

    echo \"$domain\" \"$type\" \"$item\" \"$value\" has been successfully added to your limits.conf file.
    # the correct form would be:
    # printf '"%s" "%s" "%s" "%s" has been successfully added to your limits.conf file.\n' "$domain" "$type" "$item" "$value"

else
    cat ~/etc/security/limits.conf | egrep -v "$domain|$type|$item" >~/etc/security/limits.conf1
    # Useless Use Of Cat (UUOC - google it). [e]grep can open files just as easily as cat can.

    rm -rf ~/etc/security/limits.conf
    # -r is for recursively removing files in a directory - inappropriate and misleading when used on a single file.

    mv ~/etc/security/limits.conf1 ~/etc/security/limits.conf
    # pointless to remove the file above when you're overwriting it here anyway

    # If your egrep above failed to create your temp file (e.g. due to memory or permissions issues) then the "mv" above would zap your real file. the correct way to do this is:
    #     egrep regexp file > tmp && mv tmp file
    # i.e. use && to only do the mv if creating the tmp file succeeded.

    echo $domain    $type    $item   $value >>~/etc/security/limits.conf
    # see previous echo comments.

    echo \"$domain\" \"$type\" \"$item\" \"$value\" has been successfully added to your limits.conf file.
    # ditto

    exit 0
    # pointless and misleading having an explicit "exit <success>" when that's what the script will do by default anyway.

fi

Comments

0

This line:

input=$(egrep -e '$domain\s+$type\s+$item' ~/etc/security/limits.conf)

requires double quotes around the regex to allow the shell to interpolate the variable values.

input=$(egrep -e "$domain\s+$type\s+$item" ~/etc/security/limits.conf)

You need to be careful with backslashes; you probably don't have to double them up in this context, but you should be sure you know why.

You should be aware that your first egrep commands is much more restrictive in what it selects than the second egrep which is used to delete data from the file. The first requires the entry with the three fields in the single line; the second only requires a match with any one of the words (and that could be part of a larger word) to delete the line.

Since ~/etc/security/limits.conf is a file, there is no need to use the -r option of rm; it is advisable not to use the -r unless you intend to remove directories.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.