使用Bash Shell脚本提取两个字符串之间的字符串

6

我看到过类似的问题,但是这种情况下没有一个解决方案似乎能够起作用。我有一个文本文件,看起来像这样

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脚本,以提取“START-OF-DATA”和“END-OF-DATA”之间的文本,但不包括它们。所以我需要的输出应该像这样。
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,文本文件名为file.txt。目前它只读取和回显整个文件。我猜测是语法上的一些小错误。如果有任何指向正确方向的指针,将不胜感激。 谢谢。

3个回答

6
使用 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| | |

2
太好了,正是我在寻找的!你们真是快速响应,我必须说:)再次感谢。 - tasslebear

2
为了让您的解决方案有效,您可以在到达"START-OF-DATA"时设置一种标识,比如说“True”(或者其他类似的标识),并在到达"END-OF-DATA"时结束。使用这种标识,您可以告诉echo在标识为"True"时(也就是您正在处理相关文本块时)输出内容。
...或者您可以使用sed:
sed -n '/START-OF-DATA/,/END-OF-DATA/ { //!p }' file.txt

谢谢你的回复,Bryn。你的解决方案完美地起作用了。我需要给@anubhava点赞,因为他的回复稍微快了一点。不过还是谢谢你。现在脚本已经正常工作了。问候。 - tasslebear
嗨bryn。你的[tag:sed]命令行比anubhava的更好。但对我来说有点神秘:我想知道//{ //!p }中是什么意思。请给一些解释或链接到解释这个的网站。谢谢;-) - oHo

1

我想添加 Perl 风格的 grep 方法,就像 这里 提到的那样:

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中描述的look-around assertions,它们用于匹配,但不包含在结果中。


1
很高兴使用预处理器,但是会打印出 START-OF-DATAEND-OF-DATA 这两行 :-/ 请尝试改进您的命令行以避免打印这两行。祝玩得愉快 :-) 干杯 - oHo
1
@olibre:感谢您指出这一点。我添加了改进的命令行。 - Michael Jaros

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接