使用bash shell脚本在2个字符串之间提取字符串

时间:2014-09-11 11:31:31

标签: linux string bash shell

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

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是我保存的shell脚本,而file.txt是它上面的文本文件。目前它只是读取并回显整个文件。我在我的语法中猜测它的东西是愚蠢的。任何指向正确方向的人都会非常感激。 感谢

3 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:2)

为了使您的解决方案有效,您可以在点击“START-OF-DATA”时显示“True”(或类似),然后在点击“END-OF-DATA”时结束。使用此标记,当标记显示为“True”时(当您在相关的文本块内时),您可以告诉echo打印。

...或者您可以使用sed:

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

答案 2 :(得分:1)

我想添加perlish grep方式,如上所述here

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)是{em>环绕声明,如perlre中所述,即它们用于匹配,但未包含在结果中。< / p>