1835550 Members
3214 Online
110078 Solutions
New Discussion

Using sed

 
SOLVED
Go to solution
Deepak BS
Occasional Contributor

Using sed

Suppose I have a file as follows:

VAR1=VALUE1
VAR1=VALUE1 #Some comment with a tab
VAR1=VALUE1 #Some comment with spaces
VAR11=VALUE11
VAR11=VALUE11 #Some comment with a tab
VAR11=VALUE11 #Some comment with spaces

I want to substitute all the VALUE1's with some other value say VALUE2, but without changing VALUE11.
Ideally the output file should be as follows

VAR1=VALUE2
VAR1=VALUE2 #Some comment with a tab
VAR1=VALUE2 #Some comment with spaces
VAR11=VALUE11
VAR11=VALUE11 #Some comment with a tab
VAR11=VALUE11 #Some comment with spaces

I tried using 'sed' with regular expressions but it doesnt seem to be working.
It would be great if somebody can enlighten me on this.

Cheers
Deepak

17 REPLIES 17
Todd McDaniel_1
Honored Contributor

Re: Using sed

Im confused... you can't define the same variable 3 different times.

Also, changing a variable for one doesnt affect the other variable.

I am really confused as to your logic, can you post again and explain further?

Changing a variable is simple, just change it from value1 to value2.
Unix, the other white meat.
DIPAK KUMAR ROY
Frequent Advisor

Re: Using sed

Search for "VAR1=VALUE1" string and replace with "VAR1=VALUE2"

Thanks
Deepak BS
Occasional Contributor

Re: Using sed

Haha, I think it sounded too generic.
OK, assume there are 2 different name value pairs.

CONFIG_FILE=$CFG_FILE
CONFIG_FILE_INPUT=$CFG_FILE_INPUT

Now, through a script I want to change CFG_FILE to CFG_FILE_TEMP. That is, I am _not_ doing it manually :)

So, if I use 'sed' to replace CFG_FILE to CFG_FILE_TEMP, then both these lines will get affected, which is what I do _not_ want.

After replacing, I want the file to be:
CONFIG_FILE=$CFG_FILE_TEMP
CONFIG_FILE_INPUT=$CFG_FILE_INPUT

and _not_

CONFIG_FILE=$CFG_FILE_TEMP
CONFIG_FILE_INPUT=$CFG_FILE_TEMP_INPUT

I hope somebody understood my simple yet unique problem :)

Cheers
Deepak

Umapathy S
Honored Contributor

Re: Using sed

If you have vim, then open the file and do like this :%s:\:VALUE2:g

This will do. I think the gnu versions of sed support this.

HTH,
Umapathy
Arise Awake and Stop NOT till the goal is Reached!
Deepak BS
Occasional Contributor

Re: Using sed

I am doing it non-interactively. So, I cant use vi, vim etc
H.Merijn Brand (procura
Honored Contributor
Solution

Re: Using sed

# perl -pe's/\bVALUE1\b/VALUE2/g' file

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Todd McDaniel_1
Honored Contributor

Re: Using sed

Here is a sed option...if you want to change value to val, in this example.

sed 's/CFG_FILE/CFG_FILE_TEMP/g' < file.in > file.out
Unix, the other white meat.
Elmar P. Kolkman
Honored Contributor

Re: Using sed

What you need to do is define a way for your editor (sed/perl/awk/...) to find out what to change and what not. Merijn/Procura did it with the \b meaning a blank (I think, don't have docs to verify it right now), but does this work correctly? Since there is a '=' instead of a blank before what you want to change...

Using sed, it would be something like this:
sed -e 's|CFG_FILE *$|CFG_FILE_TEMP|" -e "s|CFG_FILE\( *#.*\)$|CFG_FILE_TEMP\1|" out-file

Every problem has at least one solution. Only some solutions are harder to find.
H.Merijn Brand (procura
Honored Contributor

Re: Using sed

Elmar, NOOOOO! \b in perl is a word boundary. White space is \s

\< is begin of word in vi/elvis/vim/some-versions-of-grep and \> is end of word
perl only has \b which drills down to a zero width asserion between \w (a word character) and \W|^|$ (a non-word character, begin of line, end of line)

Enjoy, Have FUN! H.Merijn
Enjoy, Have FUN! H.Merijn
Hein van den Heuvel
Honored Contributor

Re: Using sed

Am I having a bad day or is this really tricky in SED?

I can not get an regexpr to match "end-of-line" or whitepace. The $ end-of-line anchor does not seem to cut it, The (|) alternate match does not seem to cut it.

Todd: Your suggestion will replace VALUE11 by VALUE21 which was explicitly described as to be avoided, otherwise Deepak would not have posted the question!

Elmar: No, \b is a boundary, not a character which is just as well otherwise it would be 'eaten'. COmpare to ^ and $ somewhat.

Deepak: for a general solution it would seem to me you need regular subexpression to anchor your target string and be able to get the anchors back in the output.
For example, is you'd use a simple:
sed 's/LUE1[[:blank:]]/LUE2/g' xxx
The result is: VAR1=VALUE2#Some
Instead of: VAR1=VALUE2 #Some

It was easy in Perl, but with sed to best I can come up with so far is not good enough:

sed -e 's/\([^[:alnum:]]\)VALUE1\([^[:alnum:]]\)/\1VALUE2\2/g' -e 's/VALUE1$/VALUE2/' xxx

Here the last part deals with the end-of-line occurence, the other part finds the target surrounded with non-alphanumerics, remembers those surroundings and uses them with the replace string. Yuck.

In grep you can use:
grep -E 'LUE1($|[ \t])' xxx
or:
grep -E 'LUE1($|[^[:alnum:]])' xxx

So how does one match on EOL or SPACE in sed?

The $ want to start a shell variable, and a simple escape (\) does not fix that I believe.

fwiw,
Hein.

Todd McDaniel_1
Honored Contributor

Re: Using sed

Okay I misread it...

This will work if you are explicit.

sed 's/CFG_FILE /CFG_FILE_TEMP/g' < file.in > file.out

Ensure there is a space after the CFG_FILE, this will only change the ones that are explicitly CFG_FILE and not the CFG_FILE_INPUT variable.
Unix, the other white meat.
Hein van den Heuvel
Honored Contributor

Re: Using sed

Sorry, but still wrong.... still did not read right.
nitpicking... nothing personal... just trying to help and all that!

Deepak was very explicit about the target potentially being followed by a space, tab or nothing.
It was implied, but not explicit, that he would not want to touch a line with 'VAR1=OTHERVALUE1 #differnt variable'

Cheers!
Hein.



Bob_Vance
Esteemed Contributor

Re: Using sed

sed \
-e 's/CFG_FILE$/CFG_FILE_TEMP/g' \
-e 's/CFG_FILE[ ]/CFG_FILE_TEMP/g'

where
. the first expression (-e) gets the end-of-line case
. the second expression (-e) gets the white-space (one or more tabs and/or blanks) and the [..] is entered in the script as a blank followed by a tab. On the command line, the tab can be entered as a ^V^I (ctl-V ctl-I) when in Posix/ksh/bash. In the Bourne shell, you can simply hit the tab key. I also noticed that you can simply hit the tab in HP-UX Posix/ksh shell. (I generally use ^V^I because it also works in Linux bash).

bv
"The lyf so short, the craft so long to lerne." - Chaucer
Hein van den Heuvel
Honored Contributor

Re: Using sed

> the second expression (-e) gets the white-space (one or more tabs and/or blanks) and the [..] is entered in the script as a blank followed by a tab.


Fine... but does that not stripe a tab or space from the text once replaced? How do you propose to return that exact character?

Hein.
John Wright_1
Advisor

Re: Using sed

Hi,

# cat sed.dat
VAR1=VALUE1
VAR1=VALUE1 #Some comment with a tab
VAR1=VALUE1 #Some comment with a space
VAR11=VALUE11
VAR11=VALUE11 # Some comment with a tab
VAR11=VALUE11 # Some comment with a space
# sed \
-e 's/VALUE1\([ ]\)/VALUE2\1/g' \
-e 's/VALUE1$/VALUE2/' sed.dat
VAR1=VALUE2
VAR1=VALUE2 #Some comment with a tab
VAR1=VALUE2 #Some comment with a space
VAR11=VALUE11
VAR11=VALUE11 # Some comment with a tab
VAR11=VALUE11 # Some comment with a space
#

In HP posix sh you type in the actual tab char in the [...] char class.

Cheers,
JW.
Bob_Vance
Esteemed Contributor

Re: Using sed

Good catch, Hein !!!
I missed that.

2 possibilities:

1. since we are finding whitespace, we *could* just replace it with a single space

sed \
-e 's/CFG_FILE$/CFG_FILE_TEMP/g' \
-e 's/CFG_FILE[ ]/CFG_FILE_TEMP /g'

2. better, we could just save the matching character

sed \
-e 's/CFG_FILE$/CFG_FILE_TEMP/g' \
-e 's/CFG_FILE\([ ]\)/CFG_FILE_TEMP\1/g'

The \(...\) saves the characters ... and they are "recalled" via \1.
If you have more than one \(...\) in the match string, they are recalled by occurrence in the replacement string:
\1 then \2 then \3 , etc.


bv
"The lyf so short, the craft so long to lerne." - Chaucer
rmueller58
Valued Contributor

Re: Using sed

I prefer
perl -p -i -e s/VAR1/VAR2/g

I first set the variables in my script

for example
export dist=elk
export train=train
export fin=fin

perl -p -i -e s/$dist$train/DBNAME/g dropit

where dropit is is an sql script..

#dropit
drop database DBNAME


Works great..

happy holidays all..