Replace string with sed doesn't work

Hello,

Unfortunately I don't found any working solution for my problem :confused:

I have pass file for dovecot authorizing in this format:

user@domain.tld:{SSHA}Ykx2KVG/a2FKzjnctFFC2qFnrk9nvRmW:5000:5000::::
.
.
...

Now, I want to write some sh script for password changing for grep'ed user, in this case string: {SSHA}Ykx2KVG/a2FKzjnctFFC2qFnrk9nvRmW

#!/bin/sh

OLDPW=`grep user@domain.tld passfile | cut -d: -f2`
NEWPW=`dovecotpw -s ssha -p newpassword`

sed -e 's/$OLDPW/$NEWPW/g' passfile > tmpfile
mv tmpfile passfile

but sed command doesn't work. Output file is exactly the same as input. Generated password always starts with {SSHA} and often has special characters like "/" "+", and others...

OS: FreeBSD 8

Any help?... :slight_smile: Thanks!

First, you need to use double quotes here:

sed -e "s/$OLDPW/$NEWPW/g" passfile > tmpfile

Otherwise variables won't be expanded. Second thing is that you need to find character that is never used in generated password and use it as regex delimiter:

sed -e "s#$OLDPW#$NEWPW#g" passfile > tmpfile

Here "#" was used.

Yes, it works now :slight_smile:
Thank you very much! :b:

Be careful here. From what I'm seeing you're overwriting your passfile file with the changed passwords ONLY. This means anyone who's password wasn't changed is no longer in the passfile.

I'm not real fluent with FreeBSD but you might want to see if you can use ex. It's an inline vi editor. Your statement would look like this.

print 's/'$OLDPW'/'$NEWPW'/\nwq' | ex passfile 

Some Unix flavors can use echo, others use print. You can test it very easily by creating a text file like so;

Then from the command line use something like this.

# Insert a line of text after line 3 in a file.
print '3a\n'Inserted Line'\n.\n\nwq' | ex filename.txt

# Delete a line of text that contains the pattern "search string"
print 'g/'search string'/delete\nwq' | ex filename.txt

# Substitue all occurances of "this is a line" with "that is a line.
print '%s/'this is a line'/'that is a line'/g\nwq' | ex filename.txt

I find it quite handy for updating log / config / stat and many other types of files.

Well, sed command given by bartus11 solved my problem, and any other users in passfile who's password wasn't changed don't disappear.

Here a few lines from passfile (for dovecot auth)

user1@domain.tld:{SSHA}Hg+be1/EkLn4rmFNy+WFcaF9T2K9yWpv:5000:5000::::
user2@domain.tld:{SSHA}yTTllwdKqbQDyjBUpue9FTvyx+rW5zvx:5000:5000::::
user3@domain.tld:{SSHA}T/a56MosCHi4RFnZEhWC77Cl4EautRMQ:5000:5000::::
user4@domain.tld:{SSHA}mURhtdWsRl5C9/fLxmEu0LuuZ6ocRDrh:5000:5000::::
otheruser1@otherdomain.tld:{SSHA}Ykx2LE+fa2FKzjnctFFC2qFnrk9nvRmW:5000:5000::::
otheruser2@otherdomain.tld:{SSHA}ex67n9fe6BEtniu71xN1JrF4Yna8glLb:5000:5000::::

my script get parameter $1 from command line as user@domain.tld then grep line in passfile for this user password only

OLDPW=`grep $1 passfile | cut -d: -f2`

so now variable "OLDPW" keeps password only. Then variable "NEWPW" keeps new password generated by `dovecotpw` command, sed do replacement and writes changes do tmpfile, finally `mv` gives me a new passfile with new password for user@domain.tld only.

Anyway, thanks for your tips :b:

You're absolutely right. Sorry, I use ex instead of sed so much, I start thinking of them as interchangeable, but they're not.

I would have used something like this. Note: AFAIK, this only works under ksh.

#!/bin/ksh
print "%s/`grep $1 passfile | awk -F: '{print $2}'`/`dovecotpw -s ssha -p newpassword`/g\nwq" | ex passfile

In this case, had sed been used and dumped to a temp file, then moved back, the other users would have been lost.

I stand (actually, sit) corrected. :wink:

Regards