How to replace a path with another path in sed? [duplicate]
Asked Answered
G

7

94

I have a csh script (although I can change languages if it has any relevance) where I have to:

sed s/AAA/BBB/ file

The problem is that AAA and BBB are paths, and so contain '/'. AAA is fixed, so I can say:

sed s/\\\/A\\\/A\\\A/BBB/ file

However, BBB is based on variables, including $PWD. How do I escape the '/' in $PWD?

OR is there some other way I should be doing this entirely?

Glossographer answered 21/8, 2012 at 19:7 Comment(0)
W
169

sed can use any separator instead of / in the s command. Just use something that is not encountered in your paths:

s+AAA+BBB+

and so on.

Alternatively (and if you don't want to guess), you can pre-process your path with sed to escape the slashes:

pwdesc=$(echo $PWD | sed 's_/_\\/_g')

and then do what you need with $pwdesc.

Whitsuntide answered 21/8, 2012 at 19:12 Comment(7)
Interesting. I never knew that '/' wasn't actually PART of sed... everyone seems to use it by default, so I just assumed it was mandatory. thanks.Glossographer
@LevLevitsky : Just a question :\bmatch a word but what match a path? This is because I want to append a path before a file name and I want to avoid to do it twice.Justify
@Justify Not sure I understand the question. \b matches a word boundary, btw. Maybe you should try asking a new question (or searching for existing ones)?Whitsuntide
I have "crti.oor $(crti.o)I need to apend /var/path/before them, but the sed command is called several times so it become "/var/path//var/path//var/path//var/path/crti.oor $(/var/path//var/path/crti.o).Justify
@Justify Then you probably want to match the name as something not starting with a slash: \b[^\/]\w*, or similar. But I don't see a direct connection with my answer that we are commenting on right now.Whitsuntide
That's still related to How to replace a path with another path in sed.Justify
this got to be one of the most valuable bits of knowledge Ive ever absorbed.Guenther
D
57

In circumstances where the replacement string or pattern string contain slashes, you can make use of the fact that GNU sed allows an alternative delimiter for the substitute command. Common choices for the delimiter are the pipe character | or the hash # - the best choice of delimiting character will often depend on the type of file being processed. In your case you can try

sed -i 's#/path/to/AAA#/path/to/BBB#g' your_file

Note: The g after last # is to change all occurrences in file if you want to change first ouccurence do not use g

Dehaven answered 28/10, 2014 at 8:29 Comment(0)
N
29
sed -i "s|$fileWithPath|HAHA|g" file

EDIT 1

sed -i 's|path/to/foo|path/to/bar|g' file
Nethermost answered 19/11, 2014 at 23:36 Comment(0)
A
10

Using csh for serious scripting is usually not recommended. However, that is tangential to the issue at hand.

You're probably after something like:

sed -e "s=$oldpath=$newpath="

where the shell variable $oldpath contains the value to be replaced and $newpath contains the replacement, and it is assumed that neither variable contains an equals sign. That is, you're allowed to choose the delimiter on pattern, and avoiding the usual / delimiter avoids problems with slashes in pathnames. If you think = might appear in your file names, choose something less likely to appear, such as control-A or control-G.

Anticipation answered 21/8, 2012 at 19:10 Comment(1)
This isn't serious scripting... (it's not strictly comical either, but it's only 43 lines, including whitespace and comments...) You're right, If it was much longer, I'd turn it into python.Glossographer
C
4

In my case the below method works.

sed -i 's/playstation/PS4/' input.txt

Can be also be written as

sed -i 's+playstation+PS4+' input.txt
  • sed : is stream editor

  • -i : Allows to edit the source file

  • +: Is delimiter.

I hope the above information works for you 😃.

Covey answered 18/8, 2020 at 10:14 Comment(0)
T
2

If you don't know the content of your AAA and BBB strings, you must avoid taking the risk of changing the sed separator (the classic /) for another that could be in your strings. So it is better to escape in your string the well known character used as a separator (and why not the classic /).

You can use parameter expansion ${i/p/r} to escape the slashes.

In this case ${i//p/r} for escaping all occurrences.

$p1=${p1//\//\\/}
$p2=${p2//\//\\/}
sed s/$p1/$p2/ file

Or, more concise, in one line sed s/${p1//\//\\/}/${p2//\//\\/}/ file

The string looks odd. The content of the expansion of ${p1//\//\\/} is in four parts : //, \/, /, \\/

  1. the two first pair of slashes // is a separator in parameter expansion saying we are matching all occurrences of the template,
  2. then \/ is for escaping the slash character in the search template,
  3. the / is a second separator in the expansion,
  4. and then \\/ is the replacement string, in witch the backslash must be escaped.
Tissue answered 12/1, 2015 at 14:41 Comment(0)
T
1

We just needed to get the /h/ network path references out of the path. if we pointed them back to the /c/ drive they would map to non-existant directories but resolve quickly. In my .bashrc I used

PATH=`echo $PATH | sed -e "s+/h/+/c/+g"`
Threequarter answered 12/6, 2019 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.