用bash shell脚本提取2个string之间的string

我已经看到类似的问题,但没有一个解决scheme似乎在这种情况下工作。 我有一个文本文件,看起来像这样

START-OF-FILE RUNDATE=20140910 FIRMNAME=dl FILETYPE=pc REPLYFILENAME=TEST DERIVED=yes PROGRAMFLAG=oneshot SECID=ISIN SECMASTER=yes PROGRAMNAME=getdata START-OF-FIELDS ISSUER START-OF-DATA US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | END-OF-DATA END-OF-FILE 

我正在尝试编写一个bash shell脚本来仅提取“开始数据”和“数据结束”之间的文本,但不包括这两个文本。 所以我正在寻找的输出将看起来像这样

 US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | 

我迄今为止写的代码看起来像这样

 while read line do name=$line echo $name | sed -e 's/START-OF-DATA\(.*\)END-OF-DATA/\1/' done < $1 

并从bash运行它

 ./script.sh file.txt 

其中script.sh是我保存的shell脚本,而file.txt是它读取的文本文件。 目前它只是读取和回显整个文件。 我猜我的语法有点傻。 任何正确的方向指针将不胜感激。 谢谢

使用awk你可以这样做:

 awk '/START-OF-DATA/{p=1;next} /END-OF-DATA/{p=0;exit} p' file US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | 

或者使用sed

 sed -n '/START-OF-DATA/,/END-OF-DATA/{/START-OF-DATA\|END-OF-DATA/!p;}' file US345370CN85|0|4|FORD MOTOR COMPANY|FORD MOTOR COMPANY| | | US31679BAC46|0|4|FIFTH STREET FINANCE COR|FIFTH STREET FINANCE COR| | | 

为了使您的解决方案能够正常工作,您可以在“数据开始”(“数据开始”)中显示“True”(或类似),然后在您点击“数据结束”时结束。 使用这个标记,你可以告诉回显打印标记为“真”(当你在相关的文本块内)。

…或者你可以使用sed:

 sed -n '/START-OF-DATA/,/END-OF-DATA/ { //!p }' file.txt 

我想添加grep的perlish方式,如下所述:

 grep -Pzo "(?s)START-OF-DATA.*END-OF-DATA" "$1" 

这仍然包括START-OF-DATAEND-OF-DATA标记。 为了摆脱它们,模式必须变得不那么可读:

 grep -Pzo "(?s)(?<=START-OF-DATA\n).*(?=\nEND-OF-DATA)" 

(?<=START-OF-DATA\n)(?=\nEND-OF-DATA)是perlre中描述的环视断言 ,即它们用于匹配,但不包含在结果中。