修改问题的答案
给定输入:
<?xml version="1.0" encoding="UTF-8" ?><InputRecord xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" <tag1>blah</tag1><mytag>myinfo</mytag><tag2>blah</tag2></InputRecord>
<?xml version="1.0" encoding="UTF-8" ?><InputRecord xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" <tag1>blah1</tag1><mytag>myinfo1</mytag><tag2>blah2</tag2></InputRecord>
输出应该是:
myinfo
myinfo1
暂时忽略用正则表达式解析XML通常是不明智的,这可以被视为在单行上查找开始标记和结束标记之间的文本的请求。这转化为:
starttag="<mytag>"
endtag="</mytag>"
sed -n "\%.*$starttag\(.*\)$endtag.*% s//\1/p"
POSIX sed 需要\% 表示法,以允许使用斜杠以外的其他内容作为正则表达式的分隔符。 POSIX sed 说:
... 上下文地址(由 BRE 组成,如 sed 中的正则表达式中所述,前后是分隔符,通常是 <slash>)
和:
在上下文地址中,构造"\cBREc",其中c 是<backslash> 或<newline> 以外的任何字符,应与"/BRE/" 相同。如果c 指定的字符出现在<backslash> 之后,那么它应该被认为是那个字面字符,它不会终止BRE。比如上下文地址"\xabc\xdefx",第二个x代表自己,所以BRE就是"abcxdef"。
原始版本问题的答案
如果您的 $endline 值正确,您的脚本应该可以正常工作。但是,IMNSHO,对打印范围持肯定态度会更简单:
sed -n "/$startline/,/$endline/p" input.txtt > test.txt
-n 的意思是“除非我告诉你,否则不要打印”,脚本方式“在匹配起始行的行和匹配结束行的行之间打印。
对于带有斜线的结束标签,你需要用反斜线转义斜线:
endline="<\/Nexttag>"
或者您可以使用. 代替斜线,理论上它可以匹配<XNexttag> 的开头,但可能不会。没有反斜杠可以解释为什么你得到了从开始行到文件结尾的所有内容。
论积极性的好处
考虑数据文件:
line1
line2 start1
line3
line4 end1
line5
line6 start2
line7
line8 end2
line9
并考虑 shell 和 sed 命令:
echo Positive Single
sed -n -e '/start1/,/end1/p' data
echo Negative Single
sed -e '/start1/,/end1/!d' data
echo Positive Double
sed -n -e '/start1/,/end1/p' -e '/start2/,/end2/p' data
echo Negative Double
sed -e '/start1/,/end1/!d' -e '/start2/,/end2/!d' data
运行该脚本的输出是:
$ sh sed.scripts
Positive Single
line2 start1
line3
line4 end1
Negative Single
line2 start1
line3
line4 end1
Positive Double
line2 start1
line3
line4 end1
line6 start2
line7
line8 end2
Negative Double
$
对于要匹配单个模式范围的情况,!d 公式与 -n 加上 p 公式没有问题。
但是,“正双”模式工作正常,产生了我期望的答案,用于“打印 start1 和 end1 之间的线以及之间的线start2 和 end2',而“负双精度”模式不再正常工作。我宁愿使用可扩展的版本,而不是需求变化时必须重写的版本。