【问题标题】:Extracting string between 2 strings with bash shell script使用 bash shell 脚本在 2 个字符串之间提取字符串
【发布时间】:2014-11-05 08:03:34
【问题描述】:

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

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 是上面它读取的文本文件。目前它只是读取并回显整个文件。我猜它的语法很愚蠢。任何指向正确方向的指针都将不胜感激。 谢谢

【问题讨论】:

    标签: linux string bash shell


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 感谢布林的回复。您的解决方案完美运行。我不得不投票给@anubhava,因为他的回复有点快。不过谢谢。现在让脚本正常工作。问候
    • 嗨布林。你的sed 命令行比anubhava's one 好。但对我来说有点神秘:我想知道//{ //!p } 中的含义。请给出一些解释或链接到解释这一点的网站。干杯;-)
    【解决方案3】:

    我想添加 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)"
    

    (?&lt;=START-OF-DATA\n)(?=\nEND-OF-DATA)环视断言,如perlre 中所述,即它们用于匹配,但不包含在结果中。

    【讨论】:

    • 使用 prep 很好,但是会打印 START-OF-DATAEND-OF-DATA 行:-/ 请尝试改进命令行以避免打印这两行。玩得开心:-) 干杯
    • @olibre:感谢您指出这一点。我添加了改进的命令行。
    猜你喜欢
    • 1970-01-01
    • 2020-10-15
    • 2019-03-03
    • 2012-07-07
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    相关资源
    最近更新 更多