I want to execute some sed
command for any line that matches either the and
or or
of multiple commands: e.g., sed '50,70/abc/d'
would delete all lines in range 50,70
that match /abc/
, or a way to do sed -e '10,20s/complicated/regex/' -e '30,40s/complicated/regex/
without having to retype s/compicated/regex/
问题:
回答1:
Logical-and
The and
part can be done with braces:
sed '50,70{/abc/d;}'
Further, braces can be nested for multiple and
conditions.
(The above was tested under GNU sed
. BSD sed
may differ in small but frustrating details.)
Logical-or
The or
part can be handled with branching:
sed -e '10,20{b cr;}' -e '30,40{b cr;}' -e b -e :cr -e 's/complicated/regex/' file
10,20{b cr;}
For all lines from 10 through 20, we branch to label
cr
30,40{b cr;}
For all lines from 30 through 40, we branch to label
cr
b
For all other lines, we skip the rest of the commands.
:cr
This marks the label
cr
s/complicated/regex/
This performs the substitution on lines which branched to
cr
.
With GNU sed
, the syntax for the above can be shortened a bit to:
sed '10,20{b cr}; 30,40{b cr}; b; :cr; s/complicated/regex/' file
回答2:
To delete lines from 10 to 20 and 30 to 40 matching your complicated regex with GNU sed:
sed -e '10,20bA;30,40bA;b;:A;s/complicated/regex/;d' file
or:
sed -e '10,20bA' -e '30,40bA' -e 'b;:A;s/complicated/regex/;d' file
bA
: jump to label :A
b
: a jump without label -> jump to end of script
d
: delete line
回答3:
I don't think sed
has the facility for multiple selection criteria, my advice would be to step up to awk
, where you can do something like:
awk 'NR >= 50 && NR <= 70 && /abc/ {next} {print}' inputFile
awk '(NR >= 10 and NR <= 20) || (NR >= 30 && NR <= 40) {
sub("from-regex", "to-string", $0); print }'
回答4:
sed is excellent for simple substitutions on individual lines but for anything else just use awk for clarity, robustness, portability, maintainability, etc...
awk '
(NR>=50 && NR<=70) && /abc/ { next }
(NR>=10 && NR<=20) || (NR>=30 && NR<=40) { sub(/complicated/,"regex") }
{ print }
' file