ibanja
asked on
using sed - how do I delete lines above and below a match?
using sed - I need to delete one line above and one line below any line with "ldots" on it.
In the example below all of the lines with "\backslash" and all the lines with "\end_layout" have to be deleted. There are other lines with "\end_layout" that need to stay so that's why I can't do something like:
sed -e 's/\\end_layout//'
Example:
$ grep -A1 -B1 ldots sampleDoc.lyx
\backslash
ldotsye
\end_layout
--
\backslash
ldotsforeordained
\end_layout
--
\backslash
ldotsAnd
\end_layout
--
\backslash
ldotsfor
\end_layout
--
\backslash
ldotsthat
\end_layout
--
\backslash
ldotsI
\end_layout
--
\backslash
ldotsboth
\end_layout
--
\backslash
ldotsleaving
\end_layout
--
\backslash
ldotsthat
\end_layout
--
\backslash
ldotsas
\end_layout
An explanation of the arguments would be appreciated. I've been trying to make sense of these sed one-liners to apply to my problem.
# print 1 line of context before and after regexp, with line number
# indicating where the regexp occurred (similar to "grep -A1 -B1")
sed -n -e '/regexp/{=;x;1!p;g;$!N;p; D;}' -e h
# print the line immediately before a regexp, but not the line
# containing the regexp
sed -n '/regexp/{g;1!p;};h'
# print the line immediately after a regexp, but not the line
# containing the regexp
sed -n '/regexp/{n;p;}'
Thanks,
Frank
In the example below all of the lines with "\backslash" and all the lines with "\end_layout" have to be deleted. There are other lines with "\end_layout" that need to stay so that's why I can't do something like:
sed -e 's/\\end_layout//'
Example:
$ grep -A1 -B1 ldots sampleDoc.lyx
\backslash
ldotsye
\end_layout
--
\backslash
ldotsforeordained
\end_layout
--
\backslash
ldotsAnd
\end_layout
--
\backslash
ldotsfor
\end_layout
--
\backslash
ldotsthat
\end_layout
--
\backslash
ldotsI
\end_layout
--
\backslash
ldotsboth
\end_layout
--
\backslash
ldotsleaving
\end_layout
--
\backslash
ldotsthat
\end_layout
--
\backslash
ldotsas
\end_layout
An explanation of the arguments would be appreciated. I've been trying to make sense of these sed one-liners to apply to my problem.
# print 1 line of context before and after regexp, with line number
# indicating where the regexp occurred (similar to "grep -A1 -B1")
sed -n -e '/regexp/{=;x;1!p;g;$!N;p;
# print the line immediately before a regexp, but not the line
# containing the regexp
sed -n '/regexp/{g;1!p;};h'
# print the line immediately after a regexp, but not the line
# containing the regexp
sed -n '/regexp/{n;p;}'
Thanks,
Frank
ASKER
No, because I need the rest of the file. I only want to delete the lines above and the lines below a match.
Example: I want to take this:
line one
line two
\backslash
ldotsleaving
\end_layout
last line
and turn it into this:
line one
line two
ldotsleaving
last line
Thanks
Example: I want to take this:
line one
line two
\backslash
ldotsleaving
\end_layout
last line
and turn it into this:
line one
line two
ldotsleaving
last line
Thanks
try
sed -e 'g/ldots/-1,+1d'
sed -e 'g/ldots/-1,+1d'
I'd use perl or awk instead:
awk '(s==1){s=0;next}{x++}/ldo ts/{x--;s= 1}{a[x]=$0 }END{for(x in a){print a[x]}}' yourfile
awk '(s==1){s=0;next}{x++}/ldo
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
ahoffmann,
thanks for the input but I could not get this to work. It was scrambling the document somehow. I created a short sedTest doc by running "grep -A1 -B1 ldots sampleDoc.lyx > sedTest" which produces the exact same output as in my original question - dumped to the file named sedTest. I then ran line that you gave and got the following:
$ awk '(s==1){s=0;next}{x++}/ldo ts/{x--;s= 1}{a[x]=$0 }END{for(x in a){print a[x]}}' sedTest
ldotsthat
--
--
ldotsAnd
ldotsas
--
ldotsfor
--
ldotsthat
--
ldotsI
--
ldotsboth
--
ldotsye
ldotsleaving
--
--
ldotsforeordained
thanks for the input but I could not get this to work. It was scrambling the document somehow. I created a short sedTest doc by running "grep -A1 -B1 ldots sampleDoc.lyx > sedTest" which produces the exact same output as in my original question - dumped to the file named sedTest. I then ran line that you gave and got the following:
$ awk '(s==1){s=0;next}{x++}/ldo
ldotsthat
--
--
ldotsAnd
ldotsas
--
ldotsfor
--
ldotsthat
--
ldotsI
--
ldotsboth
--
ldotsye
ldotsleaving
--
--
ldotsforeordained
ASKER
DocGyver,
That is perfect. It works and thanks so much for the explanation. That clearifies a few questions I have had about how to use some of the options in sed, especially the h and the n. I could never get them to work and didn't have any good examples to compare to.
Much appreciated,
Frank
That is perfect. It works and thanks so much for the explanation. That clearifies a few questions I have had about how to use some of the options in sed, especially the h and the n. I could never get them to work and didn't have any good examples to compare to.
Much appreciated,
Frank
you got a solution, perfect.
According my suggestion, the result you posted is exactly what it should do as I understand it from your description.
According my suggestion, the result you posted is exactly what it should do as I understand it from your description.
ASKER
ahoffmann,
"According my suggestion, the result you posted is exactly what it should do as I understand it from your description."
Sorry, I might have to be more clear. Thanks though.
"According my suggestion, the result you posted is exactly what it should do as I understand it from your description."
Sorry, I might have to be more clear. Thanks though.
sed -n '/ldot/p'