iceman225
iceman225

Reputation: 109

Replace specials characters with sed

I am trying to use a sed command to replace specials characters in my file. The characters are %> to replace by ]. I'am using sed -r s/\%>\/\]\/g but i have this error bash: /]/g: No such file or directory, looks like sed doesn't like it.

Upvotes: 1

Views: 180

Answers (3)

mklement0
mklement0

Reputation: 437803

To complement Avinash Raj's correct and helpful answer:

Since you were using an overall unquoted string (neither single- nor double-quoted), you were on the right track by \-escaping individual characters in your sed command.

However, you neglected to \-quote >, which is what caused your problem:

  • > is one of the shell's so-called metacharacters
  • Metacharacters have special meaning and separate words
  • Thus, s/\%>\/\]\/g is mistakenly split into 2 arguments by >:
    • s/\% is passed to sed - as s/%, because the shell removes the \ instances (a process called quote removal).
      • As you can see, this is not a valid sed command, but that doesn't even come into play - see below.
    • >\/\]\/g is interpreted by the shell (bash), because it starts with output-redirection operator >; after quote removal, the shell sees >/]/g, tries to open file /]/g for writing, and fails, because your system doesn't have a subdirectory named ] in its root directory.
  • bash tries to open an output file specified by a redirection before running the command and, if it fails to open the file, does not run the command - which is what happened here:
    • bash complained about the nonexistent target directory and aborted processing of the command - sed was never even invoked.

Upshot:

  • In a string that is neither enclosed in single nor in double-quotes, you must \-quote:
    • all metacharacters: | & ; ( ) < > space tab
    • additionally, to prevent accidental pathname expansion (globbing): * ? [
    • Also note that if you need to quote (escape) characters for sed,you need to add an extra layer of quoting; for instance to instruct sed to use a literal . in the regex, you must pass \\. - two backslashes - so that sed sees the properly escaped \..
  • Given the above, it is much simpler to (habitually) use single quotes around your sed command, because it ensures that the string is passed as is to sed.

Let's compare a working version of your command to the one from Avinash Raj's answer (leaving out the -r for brevity):

sed  s/\%\>\/\]\/g  # ok - all metachars. \-quoted, others are, but needn't be quoted
sed  s/%\>/]/g      # ok - minimum \-quoting
sed 's/%>/]/g'      # simplest: single-quoted command

Upvotes: 2

hek2mgl
hek2mgl

Reputation: 157977

I'm not sure whether I got the question correctly. If you want to replace either % or > by ] then sed is not required here. Use tr in this case:

tr '%>' ']' < input.txt

If you want to replace the sequence %> by ] then the sed command as shown by @AvinashRaj is the way to go.

Upvotes: 1

Avinash Raj
Avinash Raj

Reputation: 174706

Put your sed code inside quotes and also add the file-path you want to work with and finally don't escape the sed delimiters.

$ echo '%>' | sed 's/%>/]/g'
]

ie,

sed 's/%>/]/g' file

Upvotes: 4

Related Questions