【问题标题】:Extract text between two strings repeatedly using sed or awk? [duplicate]使用 sed 或 awk 重复提取两个字符串之间的文本? [复制]
【发布时间】:2012-11-03 09:03:36
【问题描述】:

我有一个名为“plainlinks”的文件,如下所示:

13080. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94092-2012.gz
13081. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94094-2012.gz
13082. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94096-2012.gz
13083. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94097-2012.gz
13084. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94098-2012.gz
13085. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94644-2012.gz
13086. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94645-2012.gz
13087. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94995-2012.gz
13088. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-94996-2012.gz
13089. ftp://ftp3.ncdc.noaa.gov/pub/data/noaa/999999-96404-2012.gz

我需要生成如下所示的输出:

999999-94092
999999-94094
999999-94096
999999-94097
999999-94098
999999-94644
999999-94645
999999-94995
999999-94996
999999-96404

【问题讨论】:

    标签: linux sed awk grep text-processing


    【解决方案1】:

    使用sed

    sed -E 's/.*\/(.*)-.*/\1/' plainlinks
    

    输出:

    999999-94092
    999999-94094
    999999-94096
    999999-94097
    999999-94098
    999999-94644
    999999-94645
    999999-94995
    999999-94996
    999999-96404
    

    要保存对文件的更改,请使用-i 选项:

    sed -Ei 's/.*\/(.*)-.*/\1/' plainlinks
    

    或者保存到一个新文件然后重定向:

    sed -E 's/.*\/(.*)-.*/\1/' plainlinks > newfile.txt
    

    解释:

    s/    # subsitution
    .*    # match anything
    \/    # upto the last forward-slash (escaped to not confused a sed)
    (.*)  # anything after the last forward-slash (captured in brackets)
    -     # upto a hypen
    .*    # anything else left on line
    /     # end match; start replace 
    \1    # the value captured in the first (only) set of brackets
    /     # end
    

    【讨论】:

    • 非常感谢您这样做
    【解决方案2】:

    只是为了好玩。

    awk -F\/ '{print substr($7,0,12)}' plainlinks

    grep

    grep -Eo '[0-9]{6}-[0-9]{5}' plainlinks

    【讨论】:

    • +1 更简单的 grep 解决方案。
    • @sudo_o 非常感谢,+1 为您的解决方案。因为是第一。
    • 同意,为优雅的 grep 解决方案 +1
    • @sampson-chen,好的,也为你 +1。
    【解决方案3】:

    假设格式与您描述的一致,您可以使用awk

    awk 'BEGIN{FS="[/-]"; OFS="-"} {print $7, $8}' plainlinks > output_file
    

    输出:

    999999-94092
    999999-94094
    999999-94096
    999999-94097
    999999-94098
    999999-94644
    999999-94645
    999999-94995
    999999-94996
    999999-96404
    

    解释

    • awk 一次读取您的输入文件一行,将每一行分成“字段”
    • 'BEGIN{FS="[/-]"; OFS="-"} 指定输入行上使用的分隔符应为/-,它还指定输出应由- 分隔
    • {print $7, $8}' 告诉 awk 打印每行的第 7 和第 8 个字段,在本例中为 9999999xxxx
    • plainlinks 是输入文件的名称所在的位置
    • > output_file 将输出重定向到名为 output_file 的文件

    【讨论】:

      【解决方案4】:

      只用shell的参数扩展:

      while IFS= read -r line; do
          tmp=${line##*noaa/}
          echo ${tmp%-????.gz}
      done < plainlinks
      

      【讨论】:

        【解决方案5】:

        如果格式保持不变,则不需要 sed 或 awk:

        cat your_file | cut -d "/" -f 7- | cut -d "-" -f 1,2
        

        【讨论】:

        • 如果格式不一样,sed 和 awk 解决方案会像这样破坏。 :)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-14
        • 2015-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多