67

Let's suppose I have this variable:

DATE="04\Jun\2014:15:54:26"

Therein I need to replace \ with \/ in order to get the string:

"04\/Jun\/2014:15:54:26"

I tried tr as follows:

echo "04\Jun\2014:15:54:26" | tr  '\' '\\/'

But this results in: "04\Jun\2014:15:54:26".

It does not satisfy me. Can anyone help?

Daniel
  • 8,655
  • 5
  • 60
  • 87
user109447
  • 1,069
  • 1
  • 10
  • 20
  • `man tr` would tell you why it doesn't work. You could use `sed`. – devnull Jun 06 '14 at 08:49
  • Why not create DATE in that format ? Also if you are echoing and writing the date before tr/sed/ect why not write it in that format ? –  Jun 06 '14 at 09:06
  • 1
    What is it that you are trying to do here? Replace forward slashes with backslashes or escaping all forward slashes? This question could use some clearing up. :) – wojciii Jun 06 '14 at 10:27
  • Why do you need to escape the forward slashes in the first place? – chepner Jun 06 '14 at 12:46

5 Answers5

117

No need to use an echo + a pipe + sed.

A simple substitution variable is enough and faster:

echo ${DATE//\//\\/}

#> 04\/Jun\/2014:15:54:26
Luc-Olivier
  • 3,715
  • 2
  • 29
  • 29
  • This doesn't seem to work in Bash 4.2.25 -- it only replaces the first slash. For example: `FileDirRelativeToProjectRoot="source\scripts\components\screens\picker_view"; echo "${FileDirRelativeToProjectRoot/\\//}"` prints `source/scripts\components\screens\picker_view` – GuyPaddock Jul 22 '16 at 17:17
  • 7
    Just figured it out, and this approach does work. You need to make sure you use two forward slashes after the variable name. So, in my example, `${FileDirRelativeToProjectRoot//\\//}`. Otherwise, it just replaces the first one. Somewhat subtle... – GuyPaddock Jul 22 '16 at 17:20
  • Very elegant. Love it. – deepelement May 24 '17 at 16:07
14

Use sed for substitutions:

sed 's#/#\\/#g' < filename.txt > newfilename.txt

You usually use "/" instead of the "#", but as long as it is there, it doesn't matter.

I am writing this on a windows PC so I hope it is right, you may have to escape the slashes with another slash.

sed explained, the -e lets you edit the file in place. You can use -i to create a backup automatically.

sed -e s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g index.html
CarenRose
  • 1,266
  • 1
  • 12
  • 24
n34_panda
  • 2,577
  • 5
  • 24
  • 40
9

here you go:

kent$  echo "04/Jun/2014:15:54:26"|sed 's#/#\\/#g'  
04\/Jun\/2014:15:54:26

your tr line was not correct, you may mis-understand what tr does, tr 'abc' 'xyz' will change a->x, b->y, c->z,not changing whole abc->xyz..

Kent
  • 189,393
  • 32
  • 233
  • 301
9

You can also escape the slashes, with a slightly less readable solution than with hashes:

echo "04/Jun/2014:15:54:26" | sed 's/\//\\\//g'
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
miguelmorin
  • 5,025
  • 4
  • 29
  • 64
7

This has not been said in other answers so I thought I'd add some clarifications:

tr uses two sets of characters for replacement, and the characters from the first set are replaced with those from the second set in a one-to-one correspondance. The manpage states that

SET2 is extended to length of SET1 by repeating its last character as necessary. Excess characters of SET2 are ignored.

Example:

echo abca | tr ab de    # produces decd
echo abca | tr a de     # produces dbcd, 'e' is ignored
echo abca | tr ab d     # produces ddcd, 'd' is interpreted as a replacement for 'b' too

When using sed for substitutions, you can use another character than '/' for the delimiter, which will make your expression clearer (I like to use ':', @n34_panda proposed '#' in their answer). Don't forget to use the /g modifier to replace all occurences: sed 's:/:\\/:g' with quotes or sed s:/:\\\\/:g without (backslashes have to be escaped twice).

Finally your shortest solution will probably be @Luc-Olivier's answer, involving substitution, in the following form (don't forget to escape forward slashes too when part of the expected pattern):

echo ${variable/expected/replacement}     # will replace one occurrence
echo ${variable//expected/replacement}    # will replace all occurrences
Alex M
  • 885
  • 9
  • 12