This question already has answers here:
Escape a string for a sed replace pattern
(17 answers)
Closed 1 year ago.
I want to replace American time to French time in PHP files from command line.
From date('m/d/Y \a\t h:i:s A' to date('Le d/m/Y à G:i:s'
I tried the following sed command :
sed -i "date('m/d/Y \a\t h:i:s A'&date('Le d/m/Y à G:i:s'&g" /path/file.php
It doesn't work. I think the problem comes from the antislashs in the source string \a\t
I already checked this question : sed command to replace string with slashes
I already tried to change the delimiters or escpae the anti-slashs with \\.
But nothing works. Any help is welcome.
Escape antislash like this :
sed -i "date('m/d/Y \\\\a\\\\t h:i:s A'&date('Le d/m/Y à G:i:s'&g" /path/file.php
Unless you need double quotes for the shell to interpret something (e.g. expand variables) use single instead of double quotes around strings (including scripts) in shell so you don't have to add additional escapes and jump through other hoops to avoid the shell interpreting chars/strings in the script.
Don't use metachars like & as script delimiters as at best it obfuscates your script, use a char that's always literal but doesn't appear in the script, e.g. # in this case.
To include ' in a '-delimited sed script either use '\'' or \x27.
I've never heard the term "antislash" in 40+ years of programming. The common term for the character \ is a backslash while / is a forwardslash.
To include a backslash literally in a string it has to be escaped with an additional preceding backslash, i.e. \\ instead of just \.
$ cat file
foo date('m/d/Y \a\t h:i:s A' bar
$ sed 's#date('\''m/d/Y \\a\\t h:i:s A'\''#date('\''Le d/m/Y à G:i:s'\''#g' file
foo date('Le d/m/Y à G:i:s' bar
$ sed 's#date(\x27m/d/Y \\a\\t h:i:s A\x27#date(\x27Le d/m/Y à G:i:s\x27#g' file
foo date('Le d/m/Y à G:i:s' bar
Add the -i back when you've tested it does what you want.
Related
This question already has answers here:
How to escape the ampersand character while using sed
(3 answers)
Closed 2 years ago.
My config file looks like:
KEY1=VALUE1
URL=https://drive.google.com/uc?export=download&id=myhash
KEY3=VALUE3
I'm trying to use sed to replace the URL value with another one. I got to the following:
sed -i.bak 's#URL=.*#URL=https://drive.google.com/uc?export=download&id=mynewhash#g' file.txt
But that doesn't seem to work, as I'm getting:
URL=https://drive.google.com/uc?export=downloadURL=https://drive.google.com/uc?export=download&id=mynewhash=myhash
What am I missing? Thanks
& is a special character in the replacement string provided to the s command of sed. It represents the string that matches the entire regex used to search (URL=.* in your example).
In order to represent itself it needs to be escaped with \:
sed -i.bak 's#URL=.*#URL=https://drive.google.com/uc?export=download\&id=mynewhash#g' file.txt
Type man sed in your terminal to read its documentation or read the documentation of sed online.
I have one file named `config_3_setConfigPW.ldif? containing the following line:
{pass}
on terminal, I used following commands
SLAPPASSWD=Pwd&0011
sed -i "s#{pass}#$SLAPPASSWD#" config_3_setConfigPW.ldif
It should replace {pass} to Pwd&0011 but it generates Pwd{pass}0011.
The reason is that the SLAPPASSWD shell variable is expanded before sed sees it. So sed sees:
sed -i "s#{pass}#Pwd&0011#" config_3_setConfigPW.ldif
When an "&" is on the right hand side of a pattern it means "copy the matched input", and in your case the matched input is "{pass}".
The real problem is that you would have to escape all the special characters that might arise in SLAPPASSWD, to prevent sed doing this. For example, if you had character "#" in the password, sed would think it was the end of the substitute command, and give a syntax error.
Because of this, I wouldn't use sed for this. You could try gawk or perl?
eg, this will print out the modified file in awk (though it still assumes that SLAPPASSWD contains no " character
awk -F \{pass\} ' { print $1"'${SLAPPASSWD}'"$2 } ' config_3_setConfigPW.ldif
That's because$SLAPPASSWD contains the character sequences & which is a metacharacter used by sed and evaluates to the matched text in the s command. Meaning:
sed 's/{pass}/match: &/' <<< '{pass}'
would give you:
match: {pass}
A time ago I've asked this question: "Is it possible to escape regex metacharacters reliably with sed". Answers there show how to reliably escape the password before using it as the replacement part:
pwd="Pwd&0011"
pwdEscaped="$(sed 's/[&/\]/\\&/g' <<< "$pwd")"
# Now you can safely pass $pwd to sed
sed -i "s/{pass}/$pwdEscaped/" config_3_setConfigPW.ldif
Bear in mind that sed NEVER operates on strings. The thing sed searches for is a regexp and the thing it replaces it with is string-like but has some metacharacters you need to be aware of, e.g. & or \<number>, and all of it needs to avoid using the sed delimiters, / typically.
If you want to operate on strings you need to use awk:
awk -v old="{pass}" -v new="$SLAPPASSWD" 's=index($0,old){ $0 = substr($0,1,s-1) new substr($0,s+length(old))} 1' file
Even the above would need tweaked if old or new contained escape characters.
Trying to clean up some xml text that looks like
Forest & Paper Products Manufacturing
with a sed command like
sed "s/ \& / & /"
but once sed gets done with the file, my output looks like
Forest & amp; Paper Products Manufacturing
Can't figure out why sed is putting a space after the &
I can solve this with:
sed "s/ \& / \& /"
But why do I need to quote the & with a \ prefix
in the replacement part, & indicates the matched string \0. So if you want to have literal & in replacement part, you have to escape it.
E.g
kent$ (master|✔) echo "foo"|sed 's/.*/&_bar/'
foo_bar
kent$ (master|✔) echo "foo"|sed 's/.*/\&_bar/'
&_bar
related info taken from sed's INFO page:
The REPLACEMENT can contain `\N' (N being a number from 1 to 9,
inclusive) references, which refer to the portion of the match which
is contained between the Nth `\(' and its matching `\)'. Also, the
REPLACEMENT can contain unescaped `&' characters which reference the
whole matched portion of the pattern space
and
To include a literal `\', `&', or newline in the final replacement, be
sure to precede the desired `\', `&', or newline in the REPLACEMENT with
a `\'.
This question already has answers here:
Using different delimiters in sed commands and range addresses
(3 answers)
Closed 1 year ago.
Changing the delimiter slash (/) to pipe (|) in the substitute command of sed works like below
echo hello | sed 's|hello|world|'
How can I change the delimiter slash (/) to pipe (|) in the sed insert command below?
echo hello | sed '/hello/i world'
I'm not sure what is intended by the command you mentioned:
echo hello | sed '/hello/i world'
However, I presume that you want to perform certain action on lines matching the pattern hello. Lets say you wanted to change the lines matching the pattern hello to world. In order to accomplish that, you can say:
$ echo -e "something\nhello" | sed '\|hello|{s|.*|world|}'
something
world
In order to match lines using a regexp, the following forms can be used:
/regexp/
\%regexp%
where % may be replaced by any other single character (note the preceding \ in the second case).
The manual provides more details on this.
The answer to the question asked is:
echo hello | sed '\|hello|i world'
That is how you would prepend a line before a line matching a path, and avoid Leaning Toothpick Syndrome with the escapes.
i have a little problem in sed, i want to replace the following line :
space here#Include "/usr/local/apache/conf/userdata/std/2/varr1/var2/*.conf"
or
space here# Include "/usr/local/apache/conf/userdata/std/2/varr1/varr2/*.conf"
(note the space after #)
to the following
Include "/usr/local/apache/conf/userdata/std/2/varr1/varr2/*.conf"
the following code works, with line that doesn't start with space :
sed -i "s/# Include \"\/usr\/local\/apache\/conf\/userdata\/std\/2\/$varr1\/$varr2\/\*.conf\"/Include \"\/usr\/local\/apache\/conf\/userdata\/std\/2\/$varr1\/$varr2\/\*.conf\"/" file.name
any help will be appreciated,
thank all
You don't need to write the path, just capture it:
sed -i 's!# *Include \("[^"]*"\)!Include \1!' input.file
Instead of using / as delimiter, you can pick up any character you want instead.
By example :
sed -i 's###g' file
So, no need to put backslashes on everything, this is difficult to read for humans beings.
Finally, try doing this :
sed -i 's#^ *# *Include \+"/usr/local/apache/conf/userdata/std/2/varr1/var\+2/\*\.conf"#Include "/usr/local/apache/conf/userdata/std/2/varr1/varr2/*.conf"#g' file.name
NOTE
* character mean zero or N occurrences in regex
^ character mean start of line
* & . are special characters, so they are backslashed. Later means any single character