What is wrong with this sed expression? - sed

sed 's_((checksum|compressed)=\").*(\")_\1\2_' -i filename
I am using this command to replace the checksum and compressed filed with empty? But it didn't change anything?
for example, I want change this line " checksum="XXXXX" with checksum="", and also replace
compressed="XXXX" with compressed=""
What is wrong with my sed command?

It's because sed uses a funny regex dialect by default: you have to escape capturing brackets.
If you want to use "normal" regex that you're familiar with, use the -r flag (if you're on unix, GNU sed) or the -E flag (Mac OS X BSD sed):
sed -r 's_((checksum|compressed)=\").*(\")_\1\3_' -i filename
Additionally, note that you have three sets of capturing brackets in your sed, and I think you want to change the \1\2 to \1\3. (\1 contains checksum=", \2 contains checksum, and \3 contains ").
(For interest, here's how you would do it without the extended-regexp (-r/-E) flag, note that capturing brackets and the OR | are only considered in the regex sense if they are escaped:
sed 's_\(\(checksum\|compressed\)=\"\).*\(\"\)_\1\3_' -i filename
)

This might work for you:
echo 'checksum="XXXXX" compressed="YYYYYYY"' |
sed 's/\(checksum\|compressed\)="[^"]*"/\1=""/g'
checksum="" compressed=""
In sed (without the -r switch), ()|+?{}'s must have a \ prepended to give them the qualities of grouping. alternation, one or more, zero or one and intervals. .[]* work as metacharacters either way.

Try:
sed 's/\(\(checksum\|compressed\)\)="[^"]*"/\1=""/' -i filename

Related

remove special character (^#) with sed

I want to remove "^#^#^#^#^#^#^#^#^#" from my textfile. I tried the following, but it did not work:
sed -i 's/\\^#//g' myfile.txt
sed is not generally robust against null characters. But Perl is, and tr:
tr -d '\000' <myfile.txt >newfile.txt
Some sed variants will be able to handle null bytes with the notation which works in Perl:
perl -i -pe 's/\x00//g' myfile.txt
The -i option says to replace the original file, like some sed variants also allow you to.
^# is one of the ways how to display the null byte. sed (at least the GNU one) represents it as \x00:
sed 's/\x00//g'

Parsing a line with sed using regular expression

Using sed I want to parse Heroku's log-runtime-metrics like this one:
2016-01-29T00:38:43.662697+00:00 heroku[worker.2]: source=worker.2 dyno=heroku.17664470.d3f28df1-e15f-3452-1234-5fd0e244d46f sample#memory_total=54.01MB sample#memory_rss=54.01MB sample#memory_cache=0.00MB sample#memory_swap=0.00MB sample#memory_pgpgin=17492pages sample#memory_pgpgout=3666pages
the desired output is:
worker.2: 54.01MB (54.01MB is being memory_total)
I could not manage although I tried several alternatives including:
sed -E 's/.+source=(.+) .+memory_total=(.+) .+/\1: \2/g'
What is wrong with my command? How can it be corrected?
The .+ after source= and memory_total= are both greedy, so they accept as much of the line as possible. Use [^ ] to mean "anything except a space" so that it knows where to stop.
sed -E 's/.+source=([^ ]+) .+memory_total=([^ ]+) .+/\1: \2/g'
Putting your content into https://regex101.com/ makes it really obvious what's going on.
I'd go for the old-fashioned, reliable, non-extended sed expressions and make sure that the patterns are not too greedy:
sed -e 's/.*source=\([^ ]*\) .*memory_total=\([^ ]*\) .*/\1: \2/'
The -e is not the opposite of -E, which is primarily a Mac OS X (BSD) sed option; the normal option for GNU sed is -r instead. The -e simply means that the next argument is an expression in the script.
This produces your desired output from the given line of data:
worker.2: 54.01MB
Bonus question: There are some odd lines within the stream, I can usually filter them out using a grep pipe like | grep memory_total. However if I try to use it along with the sed command, it does not work. No output is produced with this:
heroku logs -t -s heroku | grep memory_total | sed.......
Sometimes grep | sed is necessary, but it is often redundant (unless you are using a grep feature that isn't readily supported by sed, such as Perl regular expressions).
You should be able to use:
sed -n -e '/memory_total=/ s/.*source=\([^ ]*\) .*memory_total=\([^ ]*\) .*/\1: \2/p'
The -n means "don't print by default". The /memory_total=/ matches the lines you're after; the s/// content is the same as before. I removed the g suffix that was there previously; the regex would never match multiple times anyway. I added the p to print the line when the substitution occurs.

SED command to replace strings with in file

I am trying to use sed to replace strings with special characters in a text file. The sed command is becoming too much complicated. If someone could please help me with the exact command.
Code -
sed -i 's;PS1='${HOSTNAME} [$ORACLE_SID] $PWD> ';PS1="${COL_YELLOW}'CUSTOMER TEST:${HOSTNAME}:[$ORACLE_SID]:$PWD> '${COL_END}";g'
I tried to escape the special characters as below but its not working.
sed -i 's;PS1=\'\${HOSTNAME} [\$ORACLE_SID] \$PWD> \';PS1="\${COL_YELLOW}\'CUSTOMER TEST:\${HOSTNAME}:[\$ORACLE_SID]:\$PWD> \'\${COL_END}";g' .bash_profile_backup
This might work for you (GNU sed):
sed -i 's|PS1='\''${HOSTNAME} \[$ORACLE_SID\] $PWD> '\''|PS1="${COL_YELLOW}'\''CUSTOMER TEST:${HOSTNAME}:[$ORACLE_SID]:$PWD> '\''${COL_END}"|g' file
N.B. ' need to be quoted in both the pattern and replacement whereas [] needs to be escaped in the pattern only.

Combining two sed commands

I have a file r. I want to replace the words File and MINvac.pdb in it with nothing. The commands I used are
sed -i 's/File//g' /home/kanika/standard_minimizer_prosee/r
and
sed -i 's/MINvac.pdb//g' /home/kanika/standard_minimizer_prosee/r
I want to combine both sed commands into one, but I don't know the way. Can anyone help?
The file looks like this:
-6174.27 File10MINvac.pdb
-514.451 File11MINvac.pdb
4065.68 File12MINvac.pdb
-4708.64 File13MINvac.pdb
6674.54 File14MINvac.pdb
8563.58 File15MINvac.pdb
sed is a scripting language. You separate commands with semicolon or newline. Many sed dialects also allow you to pass each command as a separate -e option argument.
sed -i 's/File//g;s/MINvac\.pdb//g' /home/kanika/standard_minimizer_prosee/r
I also added a backslash to properly quote the literal dot before pdb, but in this limited context that is probably unimportant.
For completeness, here is the newline variant. Many newcomers are baffled that the shell allows literal newlines in quoted strings, but it can be convenient.
sed -i 's/File//g
s/MINvac\.pdb//g' /home/kanika/standard_minimizer_prosee/r
Of course, in this limited case, you could also combine everything into one regex:
sed -i 's/\(File\|MINvac\.pdb\)//g' /home/kanika/standard_minimizer_prosee/r
(Some sed dialects will want this without backslashes, and/or offer an option to use extended regular expressions, where they should be omitted. BSD sed, and thus also MacOS sed, demands a mandatory argument to sed -i which can however be empty, like sed -i ''.)
Use the -e flag:
sed -i -e 's/File//g' -e 's/MINvac.pdb//g' /home/kanika/standard_minimizer_prosee/r
Once you get more commands than are convenient to define with -es, it is better to store the commands in a separate file and include it with the -f flag.
In this case, you'd make a file containing:
s/File//g
s/MINvac.pdb//g
Let's call that file 'sedcommands'. You'd then use it with sed like this:
sed -i -f sedcommands /home/kanika/standard_minimizer_prosee/r
With only two commands, it's probably not worthwhile using a separate file of commands, but it is quite convenient if you have a lot of transformations to make.

replace ';' with ';\n'

How can I replace ; with ;\n (semicolon followed by a newline) in sed?
I've tried building off of
sed s/;/\\n/g file
and
sed -e '/;/G' file
but I can't get either to work
You need to cheat a bit: in bash you can say
sed $'s/;/;\\\n/g'
or, portably (POSIX):
sed "s/;/;$(printf '\\\n')/g"
sed does not portably/reliably handle backslash-escapes anywhere but in the pattern, and even there it's limited (POSIX only requires that \n be handled, not \t or the others). Note that you also need a backslash before the \n so sed doesn't read it as the end of the command.
sed -ie 's/;/;\n/g' <file>
That's assuming you want to do it inline in the file, remove the "i" and just use "-e" if that's not the case.