I\'m new to sed, so maybe someone can help me out. I\'m modifying some files and want to skip all lines that have the strings \"def\" or \"page.\" on them. How do I do this
If I understood well, you want to apply some changes to various lines except some line matching a regex, right? In this case, let us suppose I have the following file:
$ cat file
this is a def
this has no d e f
this is a page by the way
but this is no p a g e as we know ito
We want to replace all this
by that
but ignore the lines containing by def
or page
. So first we delete the lines starting with def
or page
:
/def/d;/page/d;
Then we apply our operation as usual:
s/this/that/g
The result is:
$ sed '/def/d;/page/d;s/this/that/g' file
that has no d e f
but that is no p a g e as we know ito
But if by "skip" you mean "do not apply my operations", just negate the address:
$ sed -E '/(def|page)/!s/this/that/g' file
this is a def
that has no d e f
this is a page by the way
but that is no p a g e as we know ito
The above statement correct. Interestingly, the 'or' operator is associated with "extended regular expression." So you must specify -E for "extended regular expression" because sed, by default, uses only "basic regular expressions."
For example, the following statement doesn't work:
$ sed -e '/(def|page)/!s/[A-Za-z_]*login[A-Za-z_]*/page.&/g' < file > new_file
But this statement below works:
$ sed -E '/(def|page)/!s/[A-Za-z_]*login[A-Za-z_]*/page.&/g' < file > new_file
AFAIK You can't (easily) negate matching lines with sed
, but something like will almost work:
sed '/\([^d][^e][^f][^ ]\)\|\([^p][^a][^g][^e]\)/ s/foo/bar/' FILE
it replaces foo
with bar
on the lines which does not contain def
or page
but catch is that "matching" lines must be at least 4 char long.
A better solution is to use awk
, e.g.:
awk '{ if ($0 !~ /def|page/) { print gensub("foo","bar","g") } else { print } }' FILE
HTH