Is it possible to do simple arithmetic in sed addresses?
You're right, one can't directly do math in sed1, even addresses. But you can use some trickery to do what you want:
Second-last row:
$ seq 5 | sed -n -e '${ # On the last line
> g # Replace the buffer with the hold space
> p # and print it
> }
> h' # All lines, store the current line in the hold space.
4
Between START
and END
:
$ cat test.in
1
START
2
3
END
4
$ cat test.in | sed '/^START$/,/^END$/{
> /^START$/d
> /^END$/d
> p
> }
> d'
2
3
$ cat test.in | sed -n -e '/^START$/,/^END$/!d' -e '/^START/d' -e '/^END$/d' -e p
2
3
I'm using a BSD (mac) sed
; on GNU systems you can use ;
between lines instead of a newline. Or stick it in a script.
1: Sed is Turing complete, so you can do math, but it's unwieldy at best: http://rosettacode.org/wiki/A%2BB#sed
Yes, I know, UUOC; it's for illustration only
sed regex replace with mathematics and quotation
If you use the p
option, you'll see the issue:
$ sed -E 's/(.*)(port=\")([0-9]+)(\".*)/echo \"\1\2$((\3+50))\4\"/gpe' ip.txt
echo "<AB port="$((10000+50))" address="0.0.0.0" adpcpu="1"/>"
<AB port=10050 address=0.0.0.0 adpcpu=1/>
You can workaround by using single quotes:
$ sed -E 's/(.*port=")([0-9]+)(.*)/echo \x27\1\x27$((\2+50))\x27\3\x27/pe' ip.txt
echo '<AB port="'$((10000+50))'" address="0.0.0.0" adpcpu="1"/>'
<AB port="10050" address="0.0.0.0" adpcpu="1"/>
$ sed -E 's/(.*port=")([0-9]+)(.*)/echo \x27\1\x27$((\2+50))\x27\3\x27/e' ip.txt
<AB port="10050" address="0.0.0.0" adpcpu="1"/>
I'll also suggest to use perl
instead:
$ perl -pe 's/port="\K\d+/$&+50/e' ip.txt
<AB port="10050" address="0.0.0.0" adpcpu="1"/>
How to use sed to identify patterns in multiple lines
One possible sed
solution:
sed -r 's/^[[:digit:]]+\. /# /g' <inputfile>
-r
: treat search pattern as an extended regex/^[[:digit]]+\. /# /g
: look for lines that start with 1 or more digits followed by a period and a space, and if found replace with a#
followed by a space- leave all other lines as they are (ie, don't make any changes)
For example:
$ cat datfile
1. numberedlist
2. one
3. two
where in the world is waldo
10. pickles
15. jam
# I'm just a comment
sky blue
100. bash
101. ksh
102. csh
72.don't touch this
# rubber ducky
And a test run of our sed
script:
$ sed -r 's/^[[:digit:]]+\. /# /g' datfile
# numberedlist
# one
# two
where in the world is waldo
# pickles
# jam
# I'm just a comment
sky blue
# bash
# ksh
# csh
72.don't touch this
# rubber ducky
What Does an Empty Regular Expression in a Sed Address Range Do?
Let me simplify the input file as:
Line1
Line2
Line3
Line4
Line5
and the test script as:
sed -n "/[134]/,//p"
which will print the all lines, corresponding to your test results.
As noted, the empty regex repeats the previous regex, then the sed command
above is equivalent to:
sed -n "/[134]/,/[134]/p"
BTW the address range operator of sed
works as follows:
- If the
left
address matches, returns true without evaluatingright
address on the same line (unlike the range operator ofawk
which evaluates the right
condition immediately on the same line).
Let's see how the operator works line by line.
- On the first line
Line1
, the left start address matches and
returnstrue
. - On the second line, the right stop address is evaluated without
match then the operator keepstrue
. - On the third line, the right stop address matches then it
changes the status tofalse
(after printing the line). - On the fourh line, the left start address matches and
returnstrue
again. - On the fifth line, the right stop address does not match and keeps
true
.
If you change the regex to /[135]/
, you will see a different result.
(Line1, 2, 3, 5 will be printed skipping Line4.)
Using sed to substitute mathematical expressions
You selected the PCRE2 option at regex101.com, while sed
only supports POSIX regex flavor.
Here, you are using a POSIX BRE flavor, so the expression will look like
#!/bin/bash
s="( - xi**2 + 2*xi - 1)"
sed 's/( - xi\*\*2 + 2\*xi - 1)/k1/g' <<< "$s"
See the online demo. In POSIX BRE, this expression means:
(
- a(
char (when not escaped, matches a(
char)- xi
- a fixed string\*\*
- a**
string (*
is a quantifier in POSIX BRE that means zero or more)2 + 2
- a fixed2 + 2
string as+
is a mere+
char in POSIX BRE\*
- a*
charxi - 1)
- a literalxi - 1)
fixed string,)
in POSIX BRE matches a literal)
char.
If you plan to use POSIX ERE, you will need to escape (
, )
and +
in your regex:
sed -E 's/\( - xi\*\*2 \+ 2\*xi - 1\)/k1/g'
Note the difference between -e
(that says that the next thing is the script to the commands to be executed) and -E
(that means the regex flavor is POSIX ERE).
sed + match the first word in line and the second word that begin with abc
Not a sed answer, but this is a clear translation of your requirements:
awk '$1 == "ADDRESS" && substr($2,0,3) == "abc"'
Sed: Better way to address the n-th line where n are elements of an array
sed is for doing s/old/new, that is all, and when you add a shell loop to the mix you've really gone off the rails (see https://unix.stackexchange.com/q/169716/133219). To delete lines whose numbers are stored in an array is (using seq
to generate input since no sample input/output provided in the question):
$ a=( 3 7 8 )
$ seq 10 |
awk -v a="${a[*]}" 'BEGIN{split(a,tmp); for (i in tmp) nrs[tmp[i]]} !(NR in nrs)'
1
2
4
5
6
9
10
and if you wanted to stop processing with awk once the last target line has been deleted and let tail finish the job then you could figure out the max value in the array up front and then do awk on just the part up to that last target line:
max=$( printf '%s\n' "${a[@]}" | sort -rn | head -1 )
head -"$max" file | awk '...' file > out
tail +"$((max+1))" file >> out
idk if that'd really be any faster than just letting awk process the whole file since awk is very efficient, especially when you're not referencing any fields and so it doesn't do any field splitting, but you could give it a try.
How do I remove multiple bracket within nested bracket using sed?
As it is not an easy task for sed/awk regex and relevant functions,
please let me show a perl
solution, although perl
is not tagged in
your question.
perl -i -pe 's/(?<=\$\(\().+?(?=\)\))/ $_ = $&; s#\$\{(.+?)}#$1#g; $_ /ge' "$file"
Input file example:
s=$(( ${s} ** 2 ))
sum=$(( ${a} + ${b} ))
echo $(( (${var} * ${var2}) / ${var3} ))
echo ${d} $((${t1} + ${t2})) ${e}
Modified result:
s=$(( s ** 2 ))
sum=$(( a + b ))
echo $(( (var * var2) / var3 ))
echo ${d} $((t1 + t2)) ${e}
- The perl substitution
s/pattern/expression/e
replaces the matchedpattern
with the perlexpression
instead of literal (or fixed)
replacement. You can perform a dynamic replacement with this mechanism. (?<=\$\(\().+?(?=\))
matches a substring which is preceded by$((
and followed))
. Then the matched substring will be the content within$(( .. ))
. The perl variable$&
is assigned to it.- The expression
$_ = $&; s#\$\{(.+?)}#$1#g; $_
is a perl code to remove
the paired${
and}
from the matched substring above. Theg
option
after the delimiter#
works as that ofsed
.
Count total number of pattern between two pattern (using sed if possible) in Linux
A very cryptic perl answer:
perl -nE 's/\{(.*?)\}/ say ($1 =~ tr{=}{=}) /ge'
The tr
function returns the number of characters transliterated.
With the new requirements, we can make a couple of small changes:
perl -0777 -nE 's/\{(.*?)\}/ say ($1 =~ tr{=}{=}) /ges'
-0777
reads the entire file/stream into a single string- the
s
flag to thes///
function allows.
to handle newlines like a plain character.
how to edit a line having IPv4 address using sed command
The regex you have used as POSIX BRE cannot match the expected strings due to \d
shorthand class that sed does not support, the misused dot inside a range quantifier and incorrect escaping of grouping and range quantifier delimiters.
You may use
sed -E -i 's/[0-9]{1,3}(\.[0-9]{1,3}){3}/ & iburst/g' ntp_file
The POSIX ERE (enabled with the -E
option) expression means to match
[0-9]{1,3}
- one to three digits(\.[0-9]{1,3}){3}
- three occurrences of a dot and one to three digits
The replacement pattern is & iburst
where &
stands for the whole match.
The g
flag replaces all occurrences.
Related Topics
Amazon Ses on Google Cloud Computing Instance Vm Using Postfix
Aws Ec2: How to Remount Previous Ebs Volume Using Pivot_Root
The Most Reliable Way to Terminate a Family of Processes
Determining The Independent Cpu's (Specified with Affinity Id's) for Building Atlas
Installing a Fully Functional Postgis 2.0 on Ubuntu Linux Geos/Gdal Issues
Single-File App with Xulrunner - Possible
Documentation About Device Driver Programming on Kernel 3.X
Open Website from Within Eclipse's Internal Browser
Avoid Copying of Data Between User and Kernel Space and Vice-Versa
Alpine Linux: Pmap Output Not Showing Rss
How to Store Multiple Pats/Passwords for Use by Git
How to Extract Text Which Matches Particular Fields in Text File Using Linux Commands
How to Solve Ssh: /Usr/Lib64/Libcrypto.So.10: No Version Information Available
How to Find Size of Heap Present in Linux
Udp Server Giving Segmentation Fault
How to Include Cutil.H in Linux
Shared Library Mysteriously Doesn't Get Linked to Application
How to Setup Virtualhosts to Point Two Ports on Same Ip to Different Servernames