我已经看到类似的问题,但没有一个解决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-DATA
和END-OF-DATA
标记。 为了摆脱它们,模式必须变得不那么可读:
grep -Pzo "(?s)(?<=START-OF-DATA\n).*(?=\nEND-OF-DATA)"
(?<=START-OF-DATA\n)
和(?=\nEND-OF-DATA)
是perlre中描述的环视断言 ,即它们用于匹配,但不包含在结果中。