Hard regex with sed - regex

In a script.sh file, I have the following line:
ExecStart=ssh -nN -R 46:192.168.0.1:56 192.168.0.2
I try to replace with sed the second port (56 here) knowing that its value can vary between 1 and 65535.
So I tried that without success :
sed -i -e "s/:.*[[:space/]]/other port number/2g' script.sh
Could you help me solve my regex?

You may use:
sed -i "s/:[0-9]\{1,5\} /:other port number /" script.sh
$ other_port_number="123"
$ echo "ExecStart=ssh -nN -R 46:192.168.0.1:56 192.168.0.2" | sed "s/:[0-9]\{1,5\} /:$other_port_number /"
ExecStart=ssh -nN -R 46:192.168.0.1:123 192.168.0.2

Related

grep parts of string with match and not match?

I have a log file which contains string errorCode:null or errorCode:404 etc. I want to find all occurrences where errorCode is not null.
I use:
grep -i "errorcode" -A 10 -B 10 app.2020-.* | grep -v -i "errorCode:null"`,
grep -v -i 'errorcode:[0-9]^4' -A 10 -B 10 app.2020-.*
but this is not the right regex match. How could this be done?
If you have gnu-grep then use a negative lookahead in regex as this with -P option:
grep -Pi 'errorcode(?!:null)' -A 10 -B 10 app.2020-.*
If you don't have gnu grep then try this awk:
awk '/errorcode/ && !/errorcode:null/' app.2020-.*
it would require more bit of code in awk to match equivalent of -A 10 -B 10 options of grep.
I have no idea why you are using -A 10 -B 10, I've just used the following command and everything is working fine:
grep -i "ErrorCode" test.txt | grep -v -i "Errorcode:null"
This the file content:
Errorcode:null
Errorcode:405
Errorcode:504
Nonsens
This is the output of the command:
Errorcode:405
Errorcode:504

perl regex doesn't match and include next line [duplicate]

I'm trying to use perl (v5.14.2) via a bash shell (GNU Bash-4.2) in Kubuntu (GNU/Linux) to search and replace a string that includes a newline character, but I'm not succeeding yet.
Here's the text file I'm searching:
<!-- filename: prac1.html -->
hello
kitty
blah blah blah
When I use a text editor's (Kate's) search-and-replace functionality or when I use a regex tester (http://regexpal.com/), I can easily get this regex to work:
hello\nkitty
But when using perl in the command line, none of the following commands have worked:
perl -p -i -e 's,hello\nkitty,newtext,' prac1.html
perl -p -i -e 's,hello.kitty,newtext,s' prac1.html
perl -p -i -e 's,hello.*kitty,newtext,s' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,' prac1.html
Actually, I got desperate and tried many other patterns, including all of these (different permutations in the "single-line" and "multi-line" modes):
perl -p -i -e 's,hello\nkitty,newtext,' prac1.html
perl -p -i -e 's,hello.kitty,newtext,' prac1.html
perl -p -i -e 's,hello\nkitty,newtext,s' prac1.html
perl -p -i -e 's,hello.kitty,newtext,s' prac1.html
perl -p -i -e 's,hello\nkitty,newtext,m' prac1.html
perl -p -i -e 's,hello.kitty,newtext,m' prac1.html
perl -p -i -e 's,hello\nkitty,newtext,ms' prac1.html
perl -p -i -e 's,hello.kitty,newtext,ms' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,s' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,s' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,s' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,s' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,m' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,m' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,m' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,m' prac1.html
perl -p -i -e 's,hello[\S\s]kitty,newtext,ms' prac1.html
perl -p -i -e 's,hello[\S\s]*kitty,newtext,ms' prac1.html
perl -p -i -e 's,hello$[\S\s]^kitty,newtext,ms' prac1.html
perl -p -i -e 's,hello$[\S\s]*^kitty,newtext,ms' prac1.html
(I also tried using \r \r\n \R \f \D etc., and global mode as well.)
Can anyone spot the issue or suggest a solution?
Try doing this, I make this possible by modifying the input record separator (a newline by default) :
perl -i -p00e 's,hello\nkitty,newtext,' prac1.html
from perldoc perlrun :
-0[octal/hexadecimal]
specifies the input record separator ($/ ) as an octal or hexadecimal
number. If there are no digits, the null character is the separator.
Other switches may precede or follow the digits. For example, if you
have a version of find which can print filenames terminated by the
null character, you can say this:
find . -name '*.orig' -print0 | perl -n0e unlink
The special value 00 will cause Perl to slurp files in paragraph mode.
Any value 0400 or above will cause Perl to slurp files whole, but by
convention the value 0777 is the one normally used for this purpose.
The problem is that "-p" has already implicitly wrapped this loop around your "-e", and the "<>" is splitting the input into lines, so your regexp never gets a chance to see more than one line.
LINE:
while (<>) {
... # your program goes here
} continue {
print or die "-p destination: $!\n";
}
See the perlrun manpage for more information.

substring via sed

I have 2 kind of messages:
Board2Port1TS239.124.3.20:3000
Board4UserTagZDF_pippo_MFPService8011
If I receive the message 1 (it contains Port) the output should be Board2Port1
If I receive the message 2 (it doesn't contain Port) the output should be Board4
The numbers of Board and Port are not fixed.
/bin/echo "Board2Port1TS239.124.3.20:3000" | /bin/sed -e '/Port/ s/???/???/ ; /Port/! s/???/???/'
I can't find a solution... could anyone help me? thanks
Many thanks to Novocaine for the perfect solution.
I have another questione directly related to the previous one:
via shell the solution is ok:
[root#test3 snmptt]# /bin/echo 'Board2Port1TS239.124.3.21:3000' | /bin/sed -r 's/^(Board.(Port.)*).*/\1/g'
Board2Port1
Now I have to use this command inside a SNMPTT configuration. It doesn't work.
This is the snmptt.debug report
Done performing substitution on PREEXEC line: /bin/echo 'Board2Port1TS239.124.3.21:3000' | /bin/sed -r 's/^(Board.(Port.)*).*/\1/g'
PREEXEC command: /bin/echo 'Board2Port1TS239.124.3.21:3000' | /bin/sed -r 's/^(Board.(Port.)*).*/\1/g'
command output: Board2Port1TS239.124.3.21:3000
The config file command is:
PREEXEC /bin/echo '$p2' | /bin/sed -r 's/^(Board.(Port.)*).*/\1/g'
the output "Board2Port1TS239.124.3.21:3000" is equal to the input ($p2). I don't undertstans why.
Thanks in advance
sed -r 's/^(Board.(Port.)*).*/\1/g' File
assuming you receive single message each time:
sed '/:/{s/\([0-9]\)[^0-9].*:/\1/;q};s/\([0-9]\)[^0-9].*/\1/'
should work:
kent$ sed '/:/{s/\([0-9]\)[^0-9].*:/\1/;q};s/\([0-9]\)[^0-9].*/\1/' <<< "Board2Port1TS239.124.3.20:3000"
Board23000
kent$ sed '/:/{s/\([0-9]\)[^0-9].*:/\1/;q};s/\([0-9]\)[^0-9].*/\1/' <<< "Board4whatever3000"
Board4
Assuming that the input really looks like your example, and that Port and UserTag are fixed strings:
sed -r '/Port/{s/TS.*//;n};s/UserTag.*//'

sed replace does not come up with my desired result

sudo sed -i 's!# dbdir /var/lib/munin!dbdir /var/lib/munin!g' /etc/munin/munin.conf
sudo sed -i 's!localhost 127.0.0.0/8 ::1!all!g' /etc/munin/apache.conf
Why does # dbdir /var/lib/munin does not get replace with dbdir /var/lib/munin
and
why does localhost 127.0.0.0/8 ::1 not get replaced with all?
sudo sed -i 's!# dbdir!dbdir!g' /etc/munin/munin.conf
gives a satisfactory result, only the localhost replacement question remaining.
In my munin.conf there are multiple space between dbdir and /var/lib/munin so unless you have exact info this replace would not work.
You search for only part of the text then replace the line:
awk '/dbdir/ {$0="dbdir /var/lib/munin"}1' /etc/munin/munin.conf > temp ; mv temp /etc/munin/munin.conf
or remove then # in front of the line
awk '/dbdir/ {sub(/^#/,x)}1' /etc/munin/munin.conf
EDIT:
awk '/Allow from local/ {sub(/localhost 127.0.0.0\/8 ::1/,"all")}1' /etc/munin/apache.conf

Using the eval command to create a command alias

For the life of me I cannot get the bash script to execute the alias command to set the hostname of a workstation the alias name to the WOL (Wakeup On Lan) equivalent command. I figure there must be an issue with quoting somewhere that I am missing.
#!/bin/bash
WOLHosts=`nvram get wol_hosts`
WOLList=($(echo "$WOLHosts" | grep -o '[A-F0-9]\{2\}:[A-F0-9]\{2\}:[A-F0-9]\{2\}:[A-F0-9]\{2\}:[A-F0-9]\{2\}:[A-F0-9]\{2\}=[^=]*=[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*' ))
if [ "${#WOLList[#]}" -gt 0 ]
then
for Match in ${WOLList[#]}
do
Command=`echo "$Match" | sed -r "s/([A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2})=([^=]*)=([0-9]*[.][0-9]*[.][0-9]*[.][0-9]*)/alias \2='\/usr\/sbin\/wol -i \3 \1'/"`
Name=`echo "$Match" | sed -r "s/([A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2})=([^=]*)=([0-9]*[.][0-9]*[.][0-9]*[.][0-9]*)/\2/"`
Com=`echo "$Match" | sed -r "s/([A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2}:[A-F0-9]{2})=([^=]*)=([0-9]*[.][0-9]*[.][0-9]*[.][0-9]*)/\/usr\/sbin\/wol -i \3 \1/"`
alias $Name="$Com"
eval $Command
echo "$Command"
done
fi
exit 0
Here is some sample data and output that I am currently receiving with the script:
Input (into WOLHosts):
00:1F:D0:26:72:53=Justin-PC=192.168.1.255 00:16:17:DD:12:7B=Justin-HTPC=192.168.1.255 00:1C:25:BC:C3:85=justinlaptop=192.168.1.255
The output produced by the vi WOecho "$Command" is:
alias Justin-PC='/usr/sbin/wol -i 192.168.1.255 00:1F:D0:26:72:53'
alias Justin-HTPC='/usr/sbin/wol -i 192.168.1.255 00:16:17:DD:12:7B'
alias justinlaptop='/usr/sbin/wol -i 192.168.1.255 00:1C:25:BC:C3:85'
Since you appear to be running this as a script, your current shell will not receive the aliases -- the aliases will disappear then the bash process driving the script ends.
Try: . script.sh or source script.sh