【问题标题】:fetch text between multiple strings on the same line在同一行的多个字符串之间获取文本
【发布时间】:2016-01-14 06:24:39
【问题描述】:

我想在文件上使用 bash 来提取位于两个字符串之间的文本。已经有一些答案,例如:

Print text between two strings on the same line

但我想多次出现,有时在同一行,有时在新行上。例如,从这样的文件开始:

\section{The rock outcrop pools experimental system} \label{intro:rockpools}
contain pools at their summit \parencite{brendonck_pools_2010} that have weathered into the rock over time \parencite{bayly_aquatic_2011} through chemical weathering after water collecting at the rock surface \parencite{lister_microgeomorphology_1973}.
Classification depends on dimensions \parencite{twidale_gnammas_1963}.

我想找回:

brendonck_pools_2010
bayly_aquatic_2011
lister_microgeomorphology_1973
twidale_gnammas_1963

我想 sed 应该能够做到这一点,但我不确定从哪里开始。

【问题讨论】:

  • 最好展示足够的上下文来对问题的复杂性给出一些看法。当我评论时,anubhavashowed 是为了更简单的输入。我可能会使用他的(启用 PCRE 的)grep 命令的略微修改版本,将\parencite 放在左大括号之前,然后使用sed 过滤输出以删除不需要的材料。

标签: bash awk sed grep


【解决方案1】:

这两个阶段的提取可能更容易理解,无需使用 Perl 正则表达式。

$ grep -o "parencite{[^}]*}" cite | sed 's/parencite{//;s/}//'
brendonck_pools_2010
bayly_aquatic_2011
lister_microgeomorphology_1973
twidale_gnammas_1963

或者,一如既往地 awk 来救援!

$ awk -F'[{}]' -v RS=" " '/parencite/{print $2}' cite
brendonck_pools_2010
bayly_aquatic_2011
lister_microgeomorphology_1973
twidale_gnammas_1963

【讨论】:

    【解决方案2】:

    使用grep -oP;

    grep -oP '\\parencite\{\K[^}]+' file
    brendonck_pools_2010
    bayly_aquatic_2011
    lister_microgeomorphology_1973
    twidale_gnammas_1963
    

    或者使用 gnu-awk:

    awk -v FPAT='\\\\parencite{[^}]+' '{for (i=1; i<=NF; i++) {
        sub(/\\parencite{/, "", $i); print $i}}' file
    brendonck_pools_2010
    bayly_aquatic_2011
    lister_microgeomorphology_1973
    twidale_gnammas_1963
    

    【讨论】:

    • 谢谢,这让我明白了一些道理。我更新了示例,因为文件中包含我不想打印的 {} 字符串的其他内容。你能解释一下如何告诉 grep 使用 "{" 和 "}" 吗?当我使用grep -oP 'parencite{\K[^}]+' file 时它不起作用...
    • @Shearn:你在哪个系统上?你有 GNU grep 或其他支持 PCRE 的 grep 吗?例如,您可能需要转义 {。您需要仔细阅读手册(令人沮丧地)。当您说“它不起作用”时,有什么症状?对正则表达式的投诉?根本不退货?当你报告“不工作”时,你需要明确——你看到的可能不是别人看到的。
    • 完全同意@JonathanLeffler, isn't working`并不能真正告诉我们什么是行不通的。另外关于您编辑的问题,为什么{...} 中的 2 个值不在输出中?
    • @Shearn {} 是特殊的,需要转义:\\parencite\{\K[^}]+(?&lt;=\\parencite\{).+?(?=\})grep -oP 一起使用
    • 抱歉 @JonathanLeffler 和 @anubhava 含糊不清。我正在运行 Ubuntu 15.04。 “不工作”是指没有输出。 @anubhava,您引用的两个值不打算出现在输出中,只有parencite{} 之间的值。 @glenn jackman,谢谢你的解释,grep -oP '\\parencite\{\K[^}]+' file 工作完美
    【解决方案3】:

    这可能对你有用(GNU sed):

    sed '/\\parencite{\([^}]*\)}/!d;s//\n\1\n/;s/^[^\n]*\n//;P;D' file
    

    删除任何不包含所需字符串的行。用换行符包围第一个出现的位置,并删除直到并包括第一个换行符。打印到并包含以下换行符,然后删除打印的内容并重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-27
      • 1970-01-01
      • 1970-01-01
      • 2017-10-25
      • 1970-01-01
      • 2014-04-28
      • 1970-01-01
      相关资源
      最近更新 更多