【问题标题】:Extract substrings between strings提取字符串之间的子字符串
【发布时间】:2021-09-08 02:01:28
【问题描述】:

我有一个文件如下:

###interest1 moreinterest1### sometext ###interest2###
not-interesting-line
sometext ###interest3###
sometext ###interest4### sometext othertext ###interest5### sometext ###interest6###

我想提取### 之间的所有字符串。

我想要的输出是这样的:

interest1 moreinterest1
interest2
interest3
interest4
interest5
interest6

我尝试了以下方法:

grep '###' file.txt | sed -e 's/.*###\(.*\)###.*/\1/g'

这几乎可行,但似乎只抓取每行的第一个实例,所以我的输出中的第一行只抓取

interest1 moreinterest1

而不是

interest1 moreinterest1
interest2

【问题讨论】:

    标签: sed grep unix-text-processing


    【解决方案1】:

    这里有一个awk 命令来实现这一点,它使### 字段分隔并打印每个偶数字段:

    awk -F '###' '{for (i=2; i<NF; i+=2) print $i}' file
    
    interest1 moreinterest1
    interest2
    interest3
    interest4
    interest5
    interest6
    

    这是一个替代方案 grep + sed 解决方案:

    grep -oE '###[^#]*###' file | sed -E 's/^###|###$//g'
    

    这假定### 标记之间没有# 字符。

    【讨论】:

    • 感谢@anubhava,我对我的示例进行了一些编辑。您的解决方案几乎可以工作,但我在### 之间的一些刺痛中有空格,您的解决方案似乎无法容纳这些空格。任何额外的帮助将不胜感激。
    • awk 解决方案有效,谢谢!在我的真实文件中,除了空格字符之外,我在感兴趣的区域内还有一些其他文本,所以这可能是 grep/sed 解决方案仍然不是我想要的原因。再次感谢您的帮助!
    • 确实awk 是比grep + sed 更强大的解决方案。我会把它搬上来。
    【解决方案2】:

    你可以使用pcregrep:

    pcregrep -o1 '###(.*?)###' file
    

    正则表达式 - ###(.*?)### - 匹配 ###,然后将除换行符之外的任何零个或多个字符捕获到第 1 组中,尽可能少,然后 ### 匹配 ###

    o1 选项将仅输出组 1 值。

    请参阅regex demo online

    【讨论】:

      【解决方案3】:
      sed 't x
      s/###/\
      /;D; :x
      s//\
      /;t y
      D;:y
      P;D' file
      

      将“###”替换为换行符D,如果第二次替换“###”成功,则有条件地分支到P

      【讨论】:

        【解决方案4】:

        使用 GNU awk 进行多字符 RS:

        $ awk -v RS='###' '!(NR%2)' file
        interest1 moreinterest1
        interest2
        interest3
        interest4
        interest5
        interest6
        

        【讨论】:

          【解决方案5】:

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

          sed -n 's/###/\n/g;/[^\n]*\n/{s///;P;D}' file
          

          用换行符替换所有出现的###

          如果一行包含换行符,请删除第一个换行符之前(包括第一个换行符)之前的所有字符,打印直到下一个换行符(包括以下换行符)的详细信息,删除这些详细信息并重复。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-01-31
            • 2013-12-11
            • 1970-01-01
            • 2015-08-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多