【问题标题】:Linux sed regular expressionLinux sed 正则表达式
【发布时间】:2021-05-28 07:39:10
【问题描述】:

我有一个字符串:

2021-05-27 10:40:50.678117 PID529270:TID 47545543550720:SID 1673488:TXID 786092740:QID 140: INFO:MEMCONTEXT:MemContext state: mem[cur/hi/max] = 9135 / 96586 / 96576 MB, VM[cur/hi/max] = 9161 / 21841178 / 100663296 MB

我想得到'='和'/'之间第一次出现的数字9135,现在,我的命令如下,它可以工作,但我认为它并不完美:

sed -r 's/.* = ([0-9]+) .* = .*/\1 /'

需要一个更整洁的,请帮忙建议。

【问题讨论】:

    标签: linux sed python-re


    【解决方案1】:

    你可以使用

    sed -En 's~.*= ([0-9]+) /.*=.*~\1~p'
    

    请参阅online demo。

    awk 解决方案:

    awk -F= '{gsub(/\/.*|[^0-9]/,"",$2);print $2}'
    

    见this demo。

    详情:

    • -En - E(或您的示例中的 r)启用 POSIX ERE 语法,n 抑制默认行输出
    • .*= ([0-9]+) /.*=.* - 匹配任何文本 = + 空格,将一个或多个数字捕获到组 1,然后匹配一个空格 /,然后匹配任何文本 =,然后再匹配任何文本
    • \1 - 替换为第 1 组值
    • p - 打印替换结果。

    这里,~ 用作正则表达式分隔符,以免在模式中转义 /。

    awk:

    • -F= - 将输入字段分隔符设置为 =
    • gsub(/\/.*|[^0-9]/,"",$2) - 删除任何非数字或 / 以及字符串的其余部分
    • print $2 - 打印修改后的字段 2 值。

    【讨论】:

      【解决方案2】:

      对于 Perl 兼容的正则表达式,您还可以使用 grep 使用 -P 获得第一个匹配项。

      grep -oP "^.*? = \K\d+(?= /)"
      
      • ^ 字符串开始
      • .*? 匹配尽可能少的字符
      • = 匹配空格= 和空格
      • \K\d+ 忘记到目前为止匹配的内容
      • (?= /) 断言一个空格和/ 到右边

      输出

      9135
      

      查看bash demo

      【讨论】:

        【解决方案3】:

        由于您想要第一个 = 和第一个 / 之间的材料,忽略空格,您可以使用:

        sed -E -e 's%^[^=]*= ([^/]*) /.*$%\1%'
        

        这使用扩展正则表达式 (ERE)(-E;-r 也适用于 GNU sed),并从行首搜索“非=”字符序列,即@ 987654328@ 字符,一个空格,任何不是斜线的东西(被记住),另一个空格,一个斜线,以及后面的任何东西,用记住的东西代替它。 ^ 和 $ 锚并不重要;没有它们,它也能正常工作。使用% 符号代替/,因为搜索到的模式包括/。如果您确定在= 和/ 之间除了第一个和最后一个空格之外永远不会有任何空格,您可以使用[^ /]* 代替[^/]*,并且应该会有一些小的(可能无法衡量的)性能受益。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-28
          • 1970-01-01
          • 1970-01-01
          • 2017-12-18
          相关资源
          最近更新 更多