sed - replace match containing two wildcards - sed

I'm having trouble trying to replace a match. My example file:
cat ntpd:
OPTIONS="-g"
OPTIONS="-u ntg:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u root:root -p /var/run/ntpd.pid -g"
OPTIONS="-u root:root"
OPTIONS="-u"
I'd like to replace any occurrence of "-u *:*" with "-u ntp:ntp"
I've tried variants of:
sed 's/-u\ \(.*\)\:\(.*\)/-u ntp:ntp/g' ntpd
but that's giving me results in which everything after the replacement string is being lost:
OPTIONS="-g"
OPTIONS="-u ntp:ntp
OPTIONS="-u ntp:ntp
OPTIONS="-u ntp:ntp
OPTIONS="-u"
....if I add a space after the second wildcard (.*\) like sed 's/-u\ \(.*\)\:\(.*\) /-u ntp:ntp/g' ntpd that strangely results in:
OPTIONS="-g"
OPTIONS="-u ntp:ntp-g"
OPTIONS="-u ntp:ntp-g"
OPTIONS="-u root:root"
OPTIONS="-u"
...where a line in which the pattern match no longer matches because it isn't trailed by a space no longer gets replaced (not good), and the line containing a space and more text after is finding the -g as the only remaining text, but I'd assume it would have left all -p /var/run/ntpd.pid -g trailing text.
Any sed experts out there, any/all guidance is appreciated. My desired results would be:
OPTIONS="-g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u ntp:ntp"
OPTIONS="-u"

This command should do it:
sed 's/-u\( [^:]\{1,\}:[^ ]\{1,\}\)/-u ntp:ntp/' file
Output:
OPTIONS="-g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u"
Btw, using extended posix regular expressions with -r the command becomes a bit more readable:
sed -r 's/-u( [^:]{1,}:[^ ]{1,})/-u ntp:ntp/' file

This might work for you (GNU sed):
sed -r 's/-u\s\S+:\S+/-u ntp:ntp/' file
Using \s to represent a space and \S to represent a non-space and the qualifier + to represent one or more of the preceeding character or class of characters, the regexp matches a -u followed by a single space, followed by one or more non-spaces, followed by a :, followed by one or more non-spaces.

All proposed answers work to a degree, but both have problems (a trailing " is wrongly dropped).
OPTIONS="-g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u ntp:ntp
OPTIONS="-u"
Whereas, the comment provided answer by #melpomene was the first response and ultimate solution, for this case at least.
Using sed 's/-u\ [a-zA-Z0-9_-]*:[a-zA-Z0-9_-]*/-u ntp:ntp/g' ntpd
results in the much desired:
OPTIONS="-g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
OPTIONS="-u ntp:ntp"
OPTIONS="-u"

Related

xargs lines containing -e and -n processed differently

When running the following command with xargs (GNU findutils) 4.7.0
xargs -n1 <<<"-d -e -n -o"
I get this output
-d
-o
Why is -e and -n not present in the output?
From man xargs:
[...] and executes the command (default is /bin/echo) [...]
So it runs:
echo -d
echo -e
echo -n
echo -o
But from man echo:
-n do not output the trailing newline
-e enable interpretation of backslash escapes
And echo -n outputs nothing, and echo -e outputs one empty newlines that you see in the output.

Replace value in single quotes using sed

I already know that sed uses own approach to deal with single quote but I think it still possible to use it in my automation script.
I had to replace value of fingerprint in Saltstack config file.
Current value:
#master_finger: ''
Target value
master_finger: 'some:value'
My current command which doesn't work:
$ sed -i 's/#master_finger: ''/master_finger: 'some:value'/g' /etc/salt/minion
returns:
master_finger: some:value''
How can I solve this?
just use the double quotes to enclose the script.
$ echo "#master_finger: ''" | sed "s/#master_finger: ''/master_finger: 'some:value'/"
master_finger: 'some:value'
It's not sed that's making handling of 's difficult, it's the shell because the shell does not allow 's within any '-quoted string, including scripts.
You could save the sed script in a file and run it with -f or use a here document:
$ sed -f- file <<'EOF'
s/#master_finger: ''/master_finger: 'some:value'/g
EOF
master_finger: 'some:value'
To see the difference between the above and #karakfas suggestion:
$ sed -f- file <<'EOF'
s/#master_finger: ''/master_finger: '$(date)'/g
EOF
master_finger: '$(date)'
$ sed "s/#master_finger: ''/master_finger: '$(date)'/" file
master_finger: 'Sun Feb 14 06:50:43 CST 2021'
and imagine if date was replace by rm -rf * or something worse.
Also consider:
$ sed 's/#master_finger: '\'\''/master_finger: '\''$(date)'\''/' file
master_finger: '$(date)'

Sed unterminated 's command in script

inside minor1.sed
sed -r 's/8/1/g' phone.txt
inside phone.txt
(866) 879-7647
(888) 474-7424
(371) 670-6006
(866) 266-5588
(844) 415-3955
(800) 237-2747
command issued
sed -r -f minor1.sed phone.txt
no matter what I do im given the unterminated 's command error.
minor1.sed should contain only sed expression, s/8/1/g in your case:
val#chi:~$ cat minor1.sed
s/8/1/g
val#chi:~$ sed -r -f minor1.sed phone.txt
(166) 179-7647
(111) 474-7424
(371) 670-6006
(166) 266-5511
(144) 415-3955
(100) 237-2747

How do I add the sed command inside a bash script?

I want to add below line to build.sh file to a line number 26
sed -i 's/-DskipTests //' dev/make-distribution.sh
I tried with this command
sed "26 a sed -i 's/-DskipTests //' dev/make-distribution.sh" build.sh
But this is giving error
sed: 1: "26 a sed -i 's/-DskipTe ...": command a expects \ followed by text`
Try putting it in as if it were multiline add as a workaround. Does this work for you?
sed "26 a\\sed -i 's/-DskipTests //' dev/make-distribution.sh" build.sh
You need to quote your quote since you are compounding quote-types.
c.f. the manual, though - it ought to work as it is.

Find and replace in UNIX

I'm having the following string in a file called test.txt,
test.log test1.log test2.log
I want to replace it with
test.log -A test1.log -A test2.log
I tried:
sed -i 's/.log/.log -A/g' test.txt
But the output is
test.log -A test1.log -A test2.log -A
I don't want that to be appended in the last file. Can someone help me on this?
If the arguments are separated by space and final argument in the line doesn't have spaces after it, you could use this:
$ cat ip.txt
test.log test1.log test2.log
$ sed 's/\.log /&-A /g' ip.txt
test.log -A test1.log -A test2.log
since . is a metacharacter, you have to use \. to match it literally
& in replacement section represents entire matched portion in search section
You could also use awk here, better suited for field processing and added advantage of stripping away whitespaces at start/end of line
$ awk -v OFS=' -A ' '/\.log/{$1=$1} 1' ip.txt
test.log -A test1.log -A test2.log
default input field separator(FS) is one or more contiguous whitespace, so no need to set that
-v OFS=' -A ' set space followed by -A and space as output field separator(OFS)
/\.log/ if line contains .log
$1=$1 re-build input record, so that input FS will be replaced by OFS
1 idiomatic way to print input record
note that this solution won't change a line if it doesn't contain .log