sed command does not work when a comma is present - unix

New to sed, so please bear with me...
I have a php file which contains the following line:
define('TARGET_A','044');
Id like to find that line and replace it with the following using sed:
define('TARGET_K','076');
I have tried:
$ sed -i 's/define\(\'TARGET_A\',\'044\'\)\;/define\(\'TARGET_K\',\'076\'\)\;/' myfile.php
I have tried SEVERAL variations, tried escaping the parens and removing the semicolon, nothing seems to work
ANY help at all GREATLY appreciated, thanks

That's a lot of escaping. How about... no escaping at all?
sed -i '.bak' "s/define('TARGET_A','044');/define('TARGET_K','076');/" myfile.php
Example:
cternus#astarael:~⟫ cat myfile.php
define('TARGET_A','044');
cternus#astarael:~⟫ sed -i '.bak' "s/define('TARGET_A','044');/define('TARGET_K','076');/" myfile.php
cternus#astarael:~⟫ cat myfile.php
define('TARGET_K','076');

This worked for me:
$sed -i "s/define('TARGET_A','044');/define('TARGET_K','076');/" myfile.php
I changed the argument string delimiter to make it simpler.

You can't escape 's in a '-delimited script so you need to escape back to shell with '\'' whenever you need a '. You might be tempted to use " to delimit the script instead but then you're opening it up to shell variable expansion, etc. so you need to be careful about what goes in your script and escape some characters to stop the shell from expanding them. It's much more robust (and generally makes your scripts simpler) to just stick to single quotes and escape back to shell just for the parts you NEED to:
$ sed 's/define('\''TARGET_A'\'','\''044'\'');/define('\''TARGET_K'\'','\''076'\'');/' file
define('TARGET_K','076');

Related

How to replace the html tags with SED?

i need some help with using sed in unix.
i need to Use the standard Unix command sed to process the input stream and remove all HTML tags, so that for example:
This is my link.
will be replaced by
This is my link.
I tried
sed -r 's/
<[^>]*>
//g'
but it didn't work.
This is extremely bare-bones and unlikely to catch all of the scenarious that HTML will throw at you, but if you are looking to just trim a leading and trailing < and >, then something like this might work:
sed 's/<[^>]*>//g'
But seriously, I'd use a parser.
In the general case you cannot parse HTML with regular expressions.
But, for simple case and assuming that no tag spans more than two lines, you can use:
sed -e 's/<[^<>]*>//g' -e 's/<[^<>]*$//' -e 's/^[^<>]*>//'
The first regex finds and deletes tags contained on one line. The second takes care of tags which begin on a line but end on the next. The third deletes the tails of tags which began on the previous line. I a tag can span more than two lines then something more complicated (or a better tool) is needed.

Testing a SED command for replacing text, it gives no error, but it isn't working as intended

I'm trying to search in all files a text, and replace it with the word EXAMPLE. I do the following:
for f in /home/testu/zz*; do
sed -i "s/&VAR1\s*=\s*'?[1]{4}'?/EXAMPLE/g" "$f"
done
It gives no error, the files seems to be "updated" in the filesystem, but they wont get changed. If I test that regexp with the grep command it works fine, so something must be wrong with SED, could it be SED version?
Thanks in advance.
Your current sed command parses the regular expression as a POSIX BRE compliant pattern.
In BRE POSIX, ? matches a literal ? char, and { / } also match literal { / } chars. To make a range quantifier in a BRE POSIX pattern, you need to escape {...}, \{min,max\}.
The [1] is equal to 1, so the brackets are quite redundant here.
To fix your pattern, you may replace ? with \{0,1\} (0 or 1 occurrences) and {4} with \{4\}:
sed -i "s/&VAR1\s*=\s*'\{0,1\}1\{4\}'\{0,1\}/EXAMPLE/g" "$f"
Thanks to Wiktor Stribiżew tips, we got the solution (SSED GNU 4.1.5). The resulting regexp works with grep and sed. The code was a mix of solutions at the end.
sed -i "s/&VAR1\s*=\s*'\{0,\}1\{4\}'\{0,\};\{0,\}/EXAMPLE/g" "$f"
A few things:
Things like [[:blank:]] caused error of input file.
My sed version didnt support -E, so the {} had to be escaped, didn't know that :)
Thanks again Wiktor!

Find and replace: \'

I'm trying to replace a every reference of \' with &apos; in a file
I've used variations of: sed -e s/\'/"\&apos;"/g file.txt
But they always replace every.single.(single).quote
Any help would be greatly appreciated.
Not sure it's the best solution,I could do it like this:
sed "s/[\]'/\"\&apos;\"/g" file.txt
(putting the backslash character in a character range so it doesn't interfere with the following quote, and protect with double quotes)
Or just extending your syntax, without quotes but using almost the same trick:
sed -e s/[\\]\'/"\&apos;"/g file.txt
An approach trying to conserve as much of the "single-quotedness" of the sed command as possible:
sed 's/\\'"'"'/\&apos;/g'
Just escaping \ with \\ and getting a single quote into the command with '"'"': the first single quote ends the command so far, then we have a double-quoted single quote ("'"), and finally an opening single quote for the rest of the command.
Alternatively, double quoting the whole command and escaping both the backslash and single quote:
sed "s/\\\'/\&apos;/g"
The correct syntax is:
$ echo "foo'bar" | sed 's/'\''/\&apos;/'
foo&apos;bar
Every script (sed, awk, whatever) should always be enclosed in single quotes and you just us other single quotes to stop/restart the script delimiters break out to shell for the minimal portion of the script that's absolutely necessary, in this case long enough to use \'. You need to break out to shell to specify that ' because per shell rules no script enclosed in 's can contain a ', not even if you try to escape it.
echo "foo'bar" | gawk '{gsub(/\47/,"\\&apos;")}1'
foo&apos;bar
The tricky part here is to replace a single quote with ampersand.
First in order to make the single quote manageable use its octal
code here \47 and then escaping ampersand by two back slash. And all of sudden
it becomes feasible :)

Using sed to replace text with curly braces

I am trying to find the following text
get_pins {
and replace it with
get_pins -hierarchical {proc_top_*/
I've tried using sed but I'm not sure what I'm doing wrong. I know that you need # in front of curly braces but I still can't get the command to work properly.
The closest I've come is to this:
sed 's/get_pins #{#/get_pins -hierarchical #{#proc_top_*\//g' filename.txt > output
but it doesn't do the replacement I wanted above.
#merlin2011's answer shows you how to do it with alternative delimiters, but as for why your command didn't work:
It's actually perfectly fine, if you just remove all # chars. from your statement:
sed 's/get_pins {/get_pins -hierarchical {proc_top_*\//'g filename.txt > output
There are two distinct escaping requirements involved here:
Escaping literal use of the regex delimiter: this is what you did correctly, by escaping the / as \/.
Escaping characters with special meaning inside a regex in general: this escaping is always done with \-prefixing, but in your case there is NO need for such escaping: since you're NOT using -E or -r to indicate use of extended regexes - and are therefore using a basic regex - { is actually NOT a special character, so you need NOT escape it. If, by contrast, you had used -E (-r), then you should have escaped { as \{.
The problem is not in the curly braces, it's in the /.
This is exactly why sed lets you do alternate delimiters.
The line below uses ! as a delimiter instead, and works correctly for a simple file with get_pins { in it.
sed 's!get_pins {!get_pins -hierarchical {proc_top_*/!g' Input.txt
Output:
get_pins -hierarchical {proc_top_*/
Update: Based mklement0's comment, and testing with the csh shell, the following should work in csh.
sed 's#get_pins {#get_pins -hierarchical {proc_top_*/#g' Input.txt
This awk should do the replace:
awk '{sub(/get_pins {/,"get_pins -hierarchical {proc_top_*/")}1'

Replace \n with \r\n in Unix file

I'm trying to do the opposite of this question, replacing Unix line endings with Windows line endings, so that I can use SQL Server bcp over samba to import the file. I have sed installed but not dos2unix. I tried reversing the examples but to no avail.
Here's the command I'm using.
sed -e 's/\n/\r\n/g' myfile
I executed this and then ran od -c myfile, expecting to see \r\n where there used to be \n. But there all still \n. (Or at least they appear to be. The output of od overflows my screen buffer, so I don't get to see the beginning of the file).
I haven't been able to figure out what I'm doing wrong. Any suggestions?
When faced with this, I use a simple perl one-liner:
perl -pi -e 's/\n/\r\n/' filename
because sed behavior varies, and I know this works.
What is the problem with getting dos2unix onto the machine?
What is the platform you are working with?
Do you have GNU sed or regular non-GNU sed?
On Solaris, /usr/bin/sed requires:
sed 's/$/^M/'
where I entered the '^M' by typing controlV controlM. The '$' matches at the end of the line, and replaces the end of line with the control-M. You can script that, too.
Mechanisms expecting sed to expand '\r' or '\\r' to control-M are going to be platform-specific, at best.
You don't need the -e option.
$ matches the endline character. This sed command will insert a \r character before the end of line:
sed 's/$/\r/' myfile
Just adding a \r (aka ^M, see Jonathan Leffler's answer) in front of \n is not safe because the file might have mixed mode EOL, so then you risk ending up with some lines becomming \r\r\n. The safe thing to do is first remove all '\r' characters, and then insert (a single) \r before \n.
#!/bin/sh
sed 's/^M//g' ${1+"$#"} | sed 's/$/^M/'
Updated to use ^M.
sed 's/\([^^M]\)$/\0^M/' your_file
This makes sure you only insert a \r when there is no \r before \n. This worked for me.
Try using:
echo " this is output" > input
sed 's/$/\r/g' input |od -c
Maybe if you try it this way
cat myfile | sed 's/\n/\r\n/g' > myfile.win
will work, from my understanding your just making the replacements to the console output, you need to redirect output to a file, in this case myfile.win, then you could just rename it to whatever you want. The whole script would be (running inside a directory full of this kind of files):
#!/bin/bash
for file in $(find . -type f -name '*')
do
cat $file | sed 's/\n/\r\n/g' > $file.new
mv -f $file.new $file
done

Resources