【问题标题】:How can I extract just the formatted date fields using sed or grep?如何使用 sed 或 grep 仅提取格式化的日期字段?
【发布时间】:2012-12-31 14:12:43
【问题描述】:

我需要一个 grep 或 sed 语句,它只会从该语句中取出日期:

echo 'asdfdsfa asdfs 12-Dec-13 asdasd asdf 11-Jan-12 asdasd' 

所以答案应该是这样的:

12-Dec-13 11-Jan-12

我已经获得了12-Dec-13 asdasd asdf 11-Jan-12,但我无法删除日期之间的内容。是否可以使用 sed 语句来保留第一个单词和最后一个单词,使用空格来显示哪个是最后一个单词?结果应该保持不变。

【问题讨论】:

标签: regex bash sed awk grep


【解决方案1】:

一种方式:

$ echo 'asdfdsfa asdfs 12-Dec-13 asdasd asdf 11-Jan-12 asdasd' | sed 's/.*\(..-...-..\).*\(..-...-..\).*/\1 \2/'
12-Dec-13 11-Jan-12

使搜索模式更具体地用于数字和字母:

$ echo 'asdfdsfa asdfs 12-Dec-13 asdasd asdf 11-Jan-12 asdasd' | sed 's/.*\([0-9][0-9]-[a-zA-Z]\{3\}-[0-9][0-9]\).*\([0-9][0-9]-[a-zA-Z]\{3\}-[0-9][0-9]\).*/\1 \2/'
12-Dec-13 11-Jan-12

【讨论】:

  • 如果一行中有两个以上的日期怎么办?
  • @sarathi :我回答了 OP 的确切要求。
【解决方案2】:

使用关注

echo 'asdfdsfa asdfs 12-Dec-13 asdasd asdf 11-Jan-12 asdasd' | sed 's/ /\n/g' |grep '-' | tr -d '\n' |sed 's/$/ \n/g'

输出是

12-Dec-1311-Jan-12

【讨论】:

    【解决方案3】:

    使用 POSIX 字符类

    一组 POSIX 字符类将匹配您想要的文本。例如:

    \b[[:digit:]]{2}-[[:upper:]][[:lower:]]{2}-[[:digit:]]{2}\b
    

    样本输入/输出

    以下管道将使用 GNU Grep 仅提取相关文本,然后连接日期:

    $ echo 'asdfdsfa asdfs 12-Dec-13 asdasd asdf 11-Jan-12 asdasd' |
        grep -Eo '\b[[:digit:]]{2}-[[:upper:]][[:lower:]]{2}-[[:digit:]]{2}\b' |
        xargs
    12-Dec-13 11-Jan-12
    

    【讨论】:

      【解决方案4】:

      用 awk 试试

      awk '{for(i=1; i<NF; ++i){if ($i ~ /[0-9]+[-\w]*/) print $i}}' temp.txt

      适用于任意数量的行和列

      【讨论】:

      • 如果NF 字段是日期,您应该使用i<=NF。此外,OP 可能不希望日期返回分隔(从问题中不清楚)。
      【解决方案5】:
      perl -lne '@a=/([\d]+-[a-zA-Z]{3}-[\d]+)/g;print "@a"'
      

      测试:

      > echo 'asdfdsfa 12-Dec-13 asdf 11-Jan-12 asdasd' | perl -lne '@a=/([\d]+-[a-zA-Z]{3}-[\d]+)/g;print "@a"'
      12-Dec-13 11-Jan-12
      

      【讨论】:

        【解决方案6】:

        我建议date -d。所以它甚至会验证日期。

        $ cat string 
        asdfdsfa asdfs 12-Dec-13 asdasd asdf 11-Jan-12 asdasd
        
        $ for i in `cat string`; do date -d $i &>/dev/null && echo $i; done
        12-Dec-13
        11-Jan-12
        

        【讨论】:

          【解决方案7】:
           grep -o "[0-9]\{2\}-[^0-9]\{3\}-[^a-z]\{2\}" file | sed "N;s/\n/ /g"
          

          2013 年 12 月 12 日 2012 年 1 月 11 日

          【讨论】:

            【解决方案8】:

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

            sed -r 'H;g;:a;s/\s*\n$//;t;s/\n(..-...-..)\b/\1 \n/;ta;s/\n([^0-9]+)/\n/;ta' file
            

            【讨论】:

              【解决方案9】:

              试试这个:

              echo 'asdfdsfa asdfs 12-Dec-13 asdasd asdf 11-Jan-12 asdasd'  | sed 's: :\n:g' | grep ^[0-9]
              

              【讨论】:

                【解决方案10】:

                我可以访问日志,其中日期格式愚蠢:[30/Jun/2013:08:00:45 +0200]

                但我需要将其显示为:30/Jun/2013 08:00:45

                问题是在我的 grep 语句中使用“OR”,我在 2 个分隔行上收到了 2 个匹配表达式。

                解决办法如下:

                grep -in myURL_of_interest *access.log | \ grep -Eo '(\b[[:digit:]]{2}/[[:upper:]][[:lower:]]{2}/[[:digit:]]{4}|[[:digit:]]{2}:[[:digit:]]{2}:[[:digit:]]{2}\b)' \ | paste - - -d" " > MyAccess.log

                希望对你有帮助:)

                【讨论】:

                  猜你喜欢
                  • 2013-09-09
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-09-05
                  • 1970-01-01
                  • 2023-04-03
                  • 2013-08-29
                  • 2013-10-23
                  • 1970-01-01
                  相关资源
                  最近更新 更多