Replace only single instance of a character using sed

Viewed 191

I need to replace only single instance of backslash.

Input: \\apple\\\orange\banana\\\\grape\\\\\
Output: \\apple\\\orangebanana\\\\grape\\\\\
Tried using sed 's/\\//g' which is replacing all backslashes

Note: The previous character to single backslash can be anything including alphanumeric or special characters. And it's a multiline text file.

Appreciate your help on this.

4 Answers

If you want to consider perl then lookahead and lookahead is exactly what you need here:

perl -pe 's~(?<!\\)\\(?!\\)~~g' file

\\apple\\\orangebanana\\\\grape\\\\\

Details

  • (?<!\\): Negative lookbehind to make sure that previous char is not \
  • \\: Match a \
  • (?!\\): Negative lookahead to make sure that next char is not \

If you want to use sed only then I suggest:

sed -E -e ':a' -e 's~(^|[^\\])\\([^\\]|$)~\1\2~g; ta' g

When you want to replace at most one single backslash, you can use

sed -r 's/(.*[^\]|^)\\([^\].*|$)/\1\2/g'

The command is ugly due to the possibility of a line starting or ending with a backslash (need to include the possibility ^ and $).

When you want to get rid off '\al\l \\sin\gle\slas\hes \\\on \\\\a \\\\\l\i\n\e\' , you can remove a backslash from any sequence of backslashes and afterwards put one back at any place where at least one backslash is left:

sed -r 's/\\([\]*)/\1/g;s/([\]+)/\\\1/g'

or, as suggested by @potong,

sed -E 's/\\(\\*)/\1/g;s/(\\+)/\\&/g'

I like the solution, as it mimics someone who removes one of any sequence of backslashes and tries to undo his last operation. The "bug" in his attempt is that the resulting output is missing the single slashes.

With your shown samples, please try following sed code. Written and tested with GNU sed.

sed -E 's/^(\\\\[^\]*\\\\\\)([^\]*)\\(.*)/\1\2\3/' Input_file

Explanation: Using -E option to enable ERE(extended regular expression) for this program. Then using sed's back reference capability(to save matched part into temp buffer which could be used later in substitution part) here. Creating 1st capturing group which has \\apple\\\ in it. In 2nd capturing group it has orange in it then in 3rd capturing group it has rest of line in it. Now if you see carefully we have left \ between orange and banana, which is needed as per OP's required output.

This might work for you (GNU sed):

sed 's/\>\\\<//g' file

Delete a single \ between word boundaries.

Related