SED: multiple patterns on the same line, how to match/parse first one
This might work for you:
echo "bla bla bla NUM:09011111111 bla bla bla bla NUM:08022222222 bla bla bla" |
sed 's/NUM:/\n&/g;s/[^\n]*\n\(NUM:[0-9]*\)[^\n]*/\1 /g;s/.$//'
NUM:09011111111 NUM:08022222222
The problem you have is understanding that the .*
is greedy i.e. it matches the longest match not the first match. By placing a unique character (\n
sed uses it as a line delimiter so it cannot exist in the line) in front of the string we're interested in (NUM:...
) and deleting everything that is not that unique character [^\n]*
followed by the unique character \n
, we effectively split the string into manageable pieces.
Output text between two patterns on the same line using sed command
For your current input you may use this sed
:
sed 's/.*begin \(.*\) end.*/\1/' file
not sure what is wrong
Difference is use of .*
after end
that matches text after last end
and discards in substitution.
However for your 2nd part if there are two end
words, sed
command won't work correctly as it will find last end
due to greedy matching of .*
.
e.g if your input is:
this is begin not sure what is wrong end and why not end
Then following awk
would work better:
awk -F 'begin | end' '{print $2}' file
not sure what is wrong
sed to replace multiple pairs of identical pattern on same line
You should be able to get off with a single sed
expression:
# ERE
sed -E 's/([^`$]|^)(\${1,2}[^`$]+\${1,2})([^`$]|$)/\1`\2`\3/g' test.txt
# or, if you prefer BRE (but only with GNU sed)
sed 's/\([^`$]\|^\)\(\$\{1,2\}[^`$]\+\$\{1,2\}\)\([^`$]\|$\)/\1`\2`\3/g' test.txt
gives you:
some text `$\alpha$` some text `$\alpha$` some text
some text `$\beta$` some text
some text `$\gamma$`.
some text `$\delta$`
`$\epsilon$` some text `$\epsilon$`
`$\mu$`
some text `$a$` some text `$a$` some text
some text `$b$` some text
some text `$c$`.
some text `$d$`
`$e$` some text `$e$`
`$f$`
`$$\Alpha$$`
`$$\Beta$$`
`$$A$$`
`$$B$$`
We match three groups:
- prefix: a single non-backtick or non-dollar or line beginning
- the meat: one or two
$
, followed by content, followed by one/two$
- suffix: same as prefix, except we match line ending
then print them out, quoting with backticks only the middle group. We need to anchor on those prefix and suffix to avoid that double quoting you're experiencing.
Note that the POSIX BRE (basic regular expression) form above uses several GNU extensions, namely: anchoring on line beginning and line ending used in the middle of expression (and not as the first/last character in pattern), alternation (\|
) and one-or-more duplication operator (\+
). If you need this expression to work in POSIX BRE, you'll need to break it into several (i.e. 3) subexpressions and use \{1,\}
instead of \+
.
But also note that the POSIX ERE (extended regular expressions) form given should work in all modern sed
environments, on both GNU and BSD systems.
Using sed to match on multiple patterns with one expression, and delete until a blank line
Try:
ifconfig -a | sed -r '/(eth[0-9]{1,2}:|eth100:|lo)/,/^$/d'
{1,2}
means one or two of the preceding. So, eth[0-9]{1,2}
matches eth
followed by one or two numbers.
(A|B|C)
matches either A
or B
or C
. So, (eth[0-9]{1,2}:|eth100:|lo)
matches either eth
with one or two numbers or eth100
and a colon or lo
.
The used -r
for extended regular expressions (ERE). Without -r
, sed
defaults to basic regular expressions (BRE). ON GNU sed, BRE work the same but at the cost of extra backslashes:
ifconfig -a | sed '/\(eth[0-9]\{1,2\}:\|eth100:\|lo\)/,/^$/d'
BSD/OSX
BSD (OSX) sed does not recognize the -r
option. To get extended regex, use -E
instead:
ifconfig -a | sed -E '/(eth[0-9]{1,2}:|eth100:|lo)/,/^$/d'
-E
will also work with recent versions of GNU sed
.
Find two string in same line and then replace using sed
/files|no/
means to match lines with either files
or no
, it doesn't require both words on the same line.
To match the words in either order, use /files.*no|no.*files/
.
sed -i -r -e '/files.*no|no.*files/s/red/green/' "$file"
Notice that you need another /
at the end of the pattern, before s
, and the s
operation requires /
at the end of the replacement.
And you need the -r
option to make sed
use extended regexp; otherwise you have to use \|
instead of just |
.
Match the same pattern n times on the same line using sed
This might work for you (GNU sed):
sed 's/\(<\/div>\)[^<]*/\1\n/;/^</P;D' file
Replace a </div>
followed by zero or more characters that are not a <
by itself and a newline. Print only lines that begin with a <
.
SED: insert a word/string between two patterns in the SAME LINE
Use capture groups.
sed -e 's/(pattern1)(pattern2)/\1new_word\2/'
\1
is replaced with whatever matched the first pattern, \2
gets whatever matched the second pattern.
Related Topics
Phusion Passenger Nginx Module Installer V3.0.17 Issue on Debian 6.0.5 Amd64 Due to Broken Package
How to Add a System Call via a Lkm
Using $Origin to Specify the Interpreter in Elf Binaries Isn't Working
Using Sed Replace Line in File with Another File
How to Schedule a Cron Job to Run 4Th Week of the Year
Sed: Find Pattern Over Two Lines, Not Replace After That Pattern
Print the Directory Where the 'Find' Linux Command Finds a Match
Linux Command Line Using for Loop and Formatting Results
Average of Multiple Files Without Considering Missing Values
Focas Fwlib32 Cnc Library on Linux Platform
Bash/Linux Sort by 3Rd Column Using Custom Field Seperator
Get the Pid of a Running Playbook for Use Within the Playbook
Asp Net Core Linux Err_Connection_Refused
How to Make Linux Power Off When Halt Is Run
How to Merge Two Seperate - Yet Similar - Codebases into One Svn Rep
How Provide Nested Mount of Overlayfs
Mongod Does Not Start (Mongod.Service: Failed with Result 'Signal')