【问题标题】:How to *return* *only* the nth occurrence of a regex match using sed?如何使用sed *返回* *仅*第n次出现正则表达式匹配?
【发布时间】:2014-09-10 01:04:17
【问题描述】:

信息

我有一个包含时间信息的字符串。我只需要从此字符串中获取月数。我正在尝试使用sed 来完成此操作,但我还没有太多运气。使用 bash + 命令行工具是我的要求。

当前尝试

echo "1969 years 12 months 25 days 19 hours 38 minutes 24 seconds since last release" | sed -r "s/^([0-9]+).*/\1/"

返回1969

奖金

更一般地说,我的问题是字符串的整个"1969 years 12 months" 部分。我正在使用date 来获取时间差异,但我必须考虑 1970 年的开始日期。我觉得奇怪的是,我当前的输出将 1970 表示为 1969 year and 12 months

编辑:我正在尝试从这篇文章中使用 nunk 的解决方案:

How to find the difference in days between two dates?

它适用于一切,除了几个月。月数相差(12 打印的月数)。

【问题讨论】:

  • 你为什么不用grep -Po '(?<=years )\d*(?= months)'?这将打印“年”和“月”之间的数字。
  • 如果您不向我们提供原始输入并告诉我们您正在做什么来处理它们,我们将无法解决额外问题。
  • @EtanReisner,我更新了我的帖子,提供了有关全局问题的更多详细信息。
  • 什么日期可以让你输出?
  • 示例输入:2014-09-03T14:44:48+00:00 和当前日期。

标签: regex linux bash awk sed


【解决方案1】:

这适合吗:

echo "1969 years 12 months 25 days 19 hours 38 minutes 24 seconds since last release" | sed -r 's/.* ([0-9]+) months.*/\1/'

给予

12

这里发生的事情是这样的:

  • 如果按顺序包含以下所有内容,则表达式的“匹配”部分将成功:
    • .* 任何东西
    • 一个空间
    • [0-9]+ 一位或多位数字(使用()“捕获”)
    • 另一个空间
    • months“月”字
    • .* 任何东西
  • 如果成功,保证匹配整行,因为两端都有.*
  • 另外,如果成功,匹配(整行)被替换为\1,这是一个特殊的代码,意思是“第一组捕获括号的内容。你会看到括号捕获的值以上是“月”一词前面的数字。

【讨论】:

    【解决方案2】:

    接下来我会这样做:

    str="1969 years 12 months 25 days 19 hours 38 minutes 24 seconds since last release"
    
    read y m d H M S < <(echo $(grep -oP '\d+' <<<"$str"))
    echo "month: $m"
    echo "year: $y"
    #etc for $d $H $M $S
    

    打印:

    month: 12
    year: 1969
    
    • grep 过滤掉所有数字(每一行)
    • echo 由数字组成一个空格分隔的字符串
    • 什么会读取read 并将每个数字分配给相应的变量

    【讨论】:

      【解决方案3】:

      听起来您正在尝试修复运行错误工具以区分日期的输出。只需使用 GNU awk:

      $ echo "2014-09-03T14:44:48+00:00" |
      gawk '{gsub(/[-T:+]/," "); print (systime() - mktime($0)) / (24*60*60)}'
      5.86991
      

      对输出的天数做任何你喜欢的四舍五入,例如:

      $ echo "2014-09-03T14:44:48+00:00" |
      gawk '{gsub(/[-T:+]/," "); printf "%.0f\n", (systime() - mktime($0)) / (24*60*60)}'
      6
      

      请注意,使用“%.0f”实现舍入取决于系统 - 它可能向上舍入 0.5 或向最接近的偶数舍入。如果这是一个问题,请检查您的系统并在必要时编写您自己的舍入函数。

      【讨论】:

        【解决方案4】:

        您可以使用 Perl 分离出键值对:

        $ str="1969 years 12 months 25 days 19 hours 38 minutes 24 seconds since last release"
        $ echo $str | perl -lane 'print "$1 $2"  while /(\d+)\s(\w+)/g'
        1969 years
        12 months
        25 days
        19 hours
        38 minutes
        24 seconds
        

        然后使用 grep 抓取你想要的:

        $ echo $str | perl -lane 'print "$1 $2"  while /(\d+)\s(\w+)/g' | grep 'months'
        12 months
        

        【讨论】:

          猜你喜欢
          • 2015-04-10
          • 1970-01-01
          • 2018-06-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-23
          • 2016-03-18
          相关资源
          最近更新 更多