【问题标题】:Move (or copy) regex match from line to the beginning of same line将(或复制)正则表达式匹配从行移动到同一行的开头
【发布时间】:2021-09-19 07:22:42
【问题描述】:

有没有办法使用 sed 或 awk(或其他我不知道的东西)将 RegEx 匹配从它出现在行上的位置移动或复制到同一行的开头?我对 RegEx 感到满意(我正在使用 /2021-06-26T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z/,因为我专门匹配 2021-06-26 的内容),只是不确定将 RegEx 匹配添加到它所在的行之前的聪明方法。

例如:

hello 2021-06-26T20:45:20.111Z
hello 2021-06-26T20:45:20.111Z hi
hi 2021-06-26T20:35:20.111Z yes
hola yes yes 2021-06-27T20:45:20.111Z
hello 2021-06-26T22:45:20.111Z
hey 2021-06-26T23:45:20.111Z
yo 2021-06-26T20:45:20.111Z no
salut 2021-06-26T20:45:20.111Z random words here
bonjour 2021-06-26T20:45:20.111Z

有没有办法将这些时间戳复制到每行的开头?例如

2021-06-26T20:45:20.111Z hello 2021-06-26T20:45:20.111Z
2021-06-26T20:45:20.111Z hello 2021-06-26T20:45:20.111Z hi
2021-06-26T20:35:20.111Z hi 2021-06-26T20:35:20.111Z yes
2021-06-27T20:45:20.111Z hola yes yes 2021-06-27T20:45:20.111Z
2021-06-26T22:45:20.111Z hello 2021-06-26T22:45:20.111Z
2021-06-26T23:45:20.111Z hey 2021-06-26T23:45:20.111Z
2021-06-26T20:45:20.111Z yo 2021-06-26T20:45:20.111Z no
2021-06-26T20:45:20.111Z salut 2021-06-26T20:45:20.111Z random words here
2021-06-26T20:45:20.111Z bonjour 2021-06-26T20:45:20.111Z

编辑: 谷歌搜索让我相信 & 代表 sed 匹配。此后的答案教会了我关于 \# 将编号组与 () 匹配

我尝试失败的事情:

sed -E '/[2021-06-26T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z/' ~/sedtest
sed '/2021-06-26T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z/' ~/sedtest
sed -E '/2021-06-26T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z/' ~/sedtest
sed -E -n '/2021-06-26T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z/' ~/sedtest

【问题讨论】:

    标签: regex bash awk sed


    【解决方案1】:

    sed 可以使用群组() 和引用\1 来做到这一点:

    sed -E 's/(.*)(2021-06-26T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z)/\2 \1\2/'
    

    【讨论】:

    • 啊,就是这么简单。因此,如果我理解正确,则末尾的替换(\2 \1\2/)采用第 2 组(日期正则表达式)并将其添加到第 1 组和第 2 组的开头并带有空格。太棒了。非常感谢!
    【解决方案2】:

    如果您对当前的正则表达式感到满意,并且不需要匹配 > 1 个匹配项,那么您只需要 .* + 一个子表达式:

    sed -E 's/.*(2021-06-26T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z)/\1 &/' file
    

    【讨论】:

      【解决方案3】:

      您的正则表达式似乎仅适用于日期 2021-06-26

      要使其匹配正则表达式为您工作的所有日期:

      sed -E 's/^(.*([0-9]{4}(-[0-9]{2}){2}T([0-9]{2}:){2}[0-9]{2}\.[0-9]{3}Z))/\2 \1/' file
      
      2021-06-26T20:45:20.111Z hello 2021-06-26T20:45:20.111Z
      2021-06-26T20:45:20.111Z hello 2021-06-26T20:45:20.111Z hi
      2021-06-26T20:35:20.111Z hi 2021-06-26T20:35:20.111Z yes
      2021-06-27T20:45:20.111Z hola yes yes 2021-06-27T20:45:20.111Z
      2021-06-26T22:45:20.111Z hello 2021-06-26T22:45:20.111Z
      2021-06-26T23:45:20.111Z hey 2021-06-26T23:45:20.111Z
      2021-06-26T20:45:20.111Z yo 2021-06-26T20:45:20.111Z no
      2021-06-26T20:45:20.111Z salut 2021-06-26T20:45:20.111Z random words here
      2021-06-26T20:45:20.111Z bonjour 2021-06-26T20:45:20.111Z
      

      RegEx Demo

      【讨论】:

        【解决方案4】:

        使用awkmatch 函数也可以尝试以下代码。

        awk '
        match($0,/[0-9]+(-[0-9]+){2}T[0-9]+(:[0-9]+){2}\.[0-9]+Z/){
          $0=substr($0,RSTART,RLENGTH) OFS $0
        }
        1
        '  Input_file
        

        解释: 简单的解释是,使用awkmatch 函数来匹配正则表达式[0-9]+(-[0-9]+){2}T[0-9]+(:[0-9]+){2}\.[0-9]+Z,它基本上匹配所示样本的日期和时间。然后重新分配匹配部分的值以及当前行的值,然后打印行(编辑/未编辑的)。

        【讨论】:

          猜你喜欢
          • 2013-12-21
          • 2018-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多