sed question

Hi

I am trying to replace an extension in a file name using sed as follows:

echo $filename | sed 's/.txt/.doc/'

My objective is to replace any extension with let's say a .doc extension. Right now, my input may have two extensions; .txt and .csv. I have to replace both with a .doc extension. If I use the following code, it does not seem to work. Any idea what might be the probable cause?

echo $filename | sed 's/.txt|.csv/.doc'

Does the above usage of regular expression not work with sed or am i missing some quotes somewhere?

Any pointers would be appreciated.

Thanks
Vikas.

a=myfile.csv
b=${a%.*}.doc
echo $b   

Variable 'a' can contain any extension.

Thanks for ur reply. However, i am still interested to know whether it is possible thru sed or not. The reason is, if it contains anything else than a .txt or .csv, i dont want to convert it into .doc.

So, as of now, i just want to convert a .txt or a .csv into .doc, otherwise i want to raise an error.

TIA
Vikas.

The above becomes

echo $filename | sed -e "s/\.txt/\.doc/" -e "s/\.csv/\.doc/"

Mind you, the above will not change the actual file name. You will have to capture the modified name and then do a rename on the file.

Thanks Vino. It worked for me. Is it right to assume that the regular expression '|' does not work with sed and probably it is just meant to work with awk or grep?

Anyways, thanks again. It worked just fine.

No, its not so...

could you please post an example where do u find this controversy ?

Hi

I started the thread with the example. To make it clearer, below is the real life example :

I receive a file with a timestamp appended to it from source system. If it is a compressed file using gzip utility, source (a mainframe system) could send it in all the following possible formats:

filename.gz.timestamp
filename.GZ.timestamp
filename.Gz.timestamp
filename.gZ.timesstamp

I have to replace .gz., .Gz., .gZ., .GZ. to a single dot to make the above names as filename.timestamp. Once i am done with this, I will append a .gz suffix at the end. So at the end of this operation, i will have following gzip file

filename.timestamp.gz

I can now go ahead and unzip it. I was trying to use the following form of sed earlier using regular expression but it did not work for me..

echo $filename|sed 's/.gz.|.Gz.|.gZ.|.GZ././'

With what Vino suggested later on, i could resolve the issue but was just wondering why I could not use the above form of regular expression with sed.

Hope that makes it clearer.

there is no such pattern in the filename and no replacement and that is what is meant to be done !!!

for the above req,
it could be done in single step

echo "filename.Gz.timestamp" | sed 's/\(.*\)\.\(.*\)\.\(.*\)/\1.\3.gz/' 

I think I lost you there when you said, there is no pattern. I tried the folllowing code for a compressed file and it works:

filename.z.timestamp
filename.Z.timestamp

echo $filename|sed 's/.[zZ]././'

If above regular expression '[list of values]' works, why the one with '|' does not?

Because in regular expressions the | (pipe) symbol can mean "or", depending on your regex engine.

Instead of chipping away at this, consider reading J Friedl 'Mastering Regular Expressions' that way you'll know why.

again its the problem of pattern that is not matched,

if at all if you want to knock it down the same way you had specified,
just extend the solution,

echo $filename  | sed 's/.[gG][zZ]././' 

:confused: Thanks for your reply and i guess I am still confused. By using a '|', i meant to imply an 'or' to sed. I was telling it to convert either .gz. or .gZ. or .GZ. or .Gz. to a dot

It should not consider the '|' operator as pipe to another command as i am using it within the arguments of sed.

I am still hoping there should be some rationale behind it.

Matrixmadhan

I dont think that would be a very clean way to do it.. I mean if there is something like '|' that is allowed in regular expression and if it is supposed to work with sed, it should, right? Leaving aside all the possible solution, i guess i am more interested to know what is wrong with a use of '|'.

If it works with sed the way you said it does, what is the correct usage?

the symbol '|' you use in sed is just a '|'

when you use '|' in the sed to replace from the text, from the input string a pattern that matches inclusive of '|' is searched for.. if it finds it would replace

simplest example could be

echo "a|b" | sed 's/|/u/'
aub

it is just '|' not a pipe operator or an OR condition,
just a part of or a complete pattern by itself,

hope i am answering to what you have aksed for,
if not plz let me know :slight_smile: :slight_smile: :slight_smile:

This got very interesting actually. I was quite surprised to see that sed considered '|' as literal '|' and not any operator.

In that case, why it did not consider '[ ]' literally in my earlier reply #9? Consider the following for example

echo "acb" | sed 's/[cC]/z/'

and

echo "aCb" | sed 's/[cC]/z/'

Both give the same output as

azb

Well, I am really thankful to you for all your replies and hope I am not bugging anyone by not putting an end to this.

that is how you group to form regex with '[' and ']'

if it all those needs to be treated above literally,

echo "a[b" | sed 's/\[/h/'

You don't "or" that way for commands -

sed 's/^[ \t]*//;s/[ \t]*$//'

The snippet above trims leading blanks ; then trims trailing blanks

Note the ; which acts to separate actions

In your case you'd need several ; delimited commands - one for each possible substitution.

Thanks Jim and all

I guess I got my answer. Jim put it down nicely by saying 'you dont use "or" in commands like that'

Thanks all for your replies...