Sed: How to replace a string which includes multiple special characters? - regex

I'm trying to comment a line in /etc/sudoers through a shell script.
That's the relevant line I'd like to edit:
# grep '\!requiretty' /etc/sudoers
Defaults:nagios !requiretty
But it seems like the pattern I'm using with sed is incorrect, my tries:
# sed -i 's/^Defaults\:nagios$/#Defaults:nagios !requiretty/g' /etc/sudoers
# sed -i 's/^Defaults:nagios$/#Defaults:nagios !requiretty/g' /etc/sudoers
# sed -i 's/^Defaults:nagios$/#Defaults:nagios !requiretty/g' /etc/sudoers
# sed -i 's/^Defaults:nagios$/\#Defaults:nagios !requiretty/g' /etc/sudoers
# sed -i 's/^Defaults:nagios$/\#Defaults:nagios \!requiretty/g' /etc/sudoers
# sed -i 's/^Defaults:nagios$/^#Defaults:nagios !requiretty/g' /etc/sudoers
# sed -i 's/^Defaults\:nagios$/^#Defaults:nagios !requiretty/g' /etc/sudoers
# sed -i 's/^Defaults\:nagios$/#Defaults:nagios \!requiretty/g' /etc/sudoers
None of the above worked...
Can someone please assist me with the correct regex?
Thanks in advance

Well ... sudoers is not meant to be writable by anyone -- even root. You're supposed to edit it with the visudo command instead for security reasons.
I think you might have it backwards though since the first part of the sed substitution is the find. The second part is the replacement. So you would want to do something like:
sed -i 's/^Defaults:nagios !requiretty$/#Defaults:nagios/'
This will also remove the requiretty. If all you want is to add the # you could just do:
sed -i 's/^Defaults:nagios !requiretty$/#&/'

Related

General solutions to replace string regex preceded and followed by '\n'

I have a file in CentOS which looks like following
[root#localhost nn]# cat -A excel.log
real1$
0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I$
real2$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I$
real3$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real4$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I1^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real5$
0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I1^I0.5^I0.5^I0.5^I0.5^I$
real6$
I would like to replace \nreal[2-6]\n with \t\t\t' and have tried unsuccessfully the following
sed -i 's/\nreal[2-6]\n/\t\t\t/g' file
It seems that sed has difficulty to deal with line break. Any idea to fulfill the regex in CentOS?
Much appreciated!
If you want to consider perl then use:
perl -i -0777 -pe 's/\n(?:51[23]real|real[2-6])(?:\n|\z)/\t\t\t/g' file
If you want to avoid last real\d+ line to be replaced with \t\t\t then use:
perl -i -0777 -pe 's/\n(?:51[23]real|real[2-6])\n(?!\z)/\t\t\t/g' file
(?!\z) is negative lookahead to fail the match when we have line end just ahead of us.
With GNU sed, you need to use the -z option:
sed -i -z 's/\nreal[2-6]\n/\t\t\t/g' file
# ^^
Now, that you also want to handle specific alternations, you need to enable the POSIX ERE syntax, either with -r or -E option:
sed -i -Ez 's/\n(51[23]real|real[2-6])\n/\t\t\t/g' file

How to use PCRE Regex in SED on Mac OSX

I have the RegEx (\[!\[|!\[)(.*) that works on http://regexr.com/, however when I attempt to use it with sed like this -e 's/(\[!\[|!\[)\(.*\)//g' it does not work.
I have found an answer that suggests using the -r command instead of -e, however I am using Mac OSX El Capitan, and -r is not a supported command.
I have also found an answer that says use -E instead of -r on Mac OSX, but this did not work, and a commenter said they are not the same thing. It was also suggested to use grep instead of sed, but I am adding this search and replace to several others that are already using sed.
My code block looks like this and the search and replace in question is at the end of the sed... line:
# Transform the readme
if [ -f readme.md ]; then
mv readme.md readme.txt
if [ -f CHANGELOG.md ]; then
cat CHANGELOG.md >> readme.txt
rm CHANGELOG.md
fi
sed -i '' -e 's/^# \(.*\)$/=== \1 ===/' -e 's/ #* ===$/ ===/' -e 's/^## \(.*\)$/== \1 ==/' -e 's/ #* ==$/ ==/' -e 's/^### \(.*\)$/= \1 =/' -e 's/ #* =$/ =/' -e 's/\*\*//g' -e 's/(\[!\[|!\[)\(.*\)//g' readme.txt
fi
example I want to completely remove the second line that starts with [![from:
=== CMB2 Admin Extension ===
[![Build Status](https://travis-ci.org/twoelevenjay/CMB2-Admin-Extension.svg?branch=master)](https://travis-ci.org/twoelevenjay/CMB2-Admin-Extension)
Contributors: twoelevenjay
I also want it to remove lines that start with ![ like this:
![CMB2](https://plugins.trac.wordpress.org/export/HEAD/cmb2/assets/banner-1544x500.png)
I want to completely remove the second line that starts with [![:
On OSX sed this should work for you:
sed -E '/^(\[!\[|!\[)/d'
You don't need to use a substitution; just /d would suffice.

sed string replace is giving some kind of warning?

I am using sed with grep command to replace a string. Old string is in 8 files at home location and I want to replace all of these with new string. I am using this:
#! /bin/bash
read oldstring
read newstring
sed -i -e 's/'Soldstring'/'$newstring'/' grep "$oldstring" /home/*
Now this command works but I am getting an warning:
sed: can't read grep: No such file or directory
sed: can't read oldstring: No such file or directory
Any ideas?
You probably wanted
sed -i -e "s|Soldstring|$newstring|" $(grep -l "$oldstring" /home/*)
However that form is unsafe. Better use xargs:
grep -l "$oldstring" /home/* | xargs sed -i -e "s|Soldstring|$newstring|"
And another if possible is to store on arrays:
readarray -t files < <(exec grep -l "$oldstring" /home/*)
sed -i -e "s|Soldstring|$newstring|" "${files[#]}"
You are not executing grep, you are giving it as a parameter to sed.
are you missing backticks?
sed -i -e 's/'Soldstring'/'$newstring'/' `grep "$oldstring" /home/*`
sed -i -e "s/$oldstring/$newstring/g" `grep -l "$oldstring" /home/*`
Just in order to clearly point out the various typos in your code:
#! /bin/bash
# ^
# extra space here (not really an error I think -- but unusual)
read oldstring
read newstring
sed -i -e 's/'Soldstring'/'$newstring'/' grep "$oldstring" /home/*
# ^ ^ ^
# `S` instead of `$` here | |
# here and there
# missing backticks (`)
As a side note, I suggest backticks above, but, since you are using bash, the syntax $(grep ....) is probably better than the classic Bourne Shell syntax `grep ....`. Finally, as suggested by konsolebox, "command nesting" might be unsafe, for example, in this case, if some file names contain spaces.

sed match dates in wordpress url

Using sed I'm having a problem trying to match and delete blog entries from a txt file before creating a sitemap.xml
# Contents of filename:
# http://www.example.com/2008/10/article3.html
# http://www.example.com/2009/11/article7.html
#!/bin/bash
hostName="www.example.com"
hostTLD="$(echo ${hostName}|cut -d . -f 3)" # results in "com"
sed -i '/\.'"${hostTLD}"'\/\([0-9]{4}\)\/\([0-9]{2}\)/d' filename
I can't figure out how to match the year/month bits. I want to remove all lines that contain ".TLD/year/month/"
I know the $hostTLD part works because I'm using it with a different match:
sed -i '/\.'"${hostTLD}"'\/category\//d' filename # works! ".TLD/category/"
You were close, but you needed to use double-quotes around your sed command and escape the braces. Try this instead:
sed -i "/\.$hostTLD\/[0-9]\{4\}\/[0-9]\{2\}/d" filename
For your second command, use this:
sed -i "/\.$hostTLD\/category\//d" filename

delete lines with sed match a special regex

I try to delete all lines that begin with some optional special chars followed by blubb:
That's the lines I want to match:
#blubb
*blubb
-blubb
blubb
That should do it, but doesn't work :(
sed "/^.?blubb$/d" -i special.conf
sed "/^[#*-]?blubb$/d" -i special.conf
Has somebody the right solution?
Use this sed command:
sed -i.old '/^[#*-]\{0,1\}blubb/d' special.conf
OR
sed -i.old -E '/^[#*-]?blubb/d' special.conf
OR
sed -i.old -r '/^[#*-]?blubb/d' special.conf