【问题标题】:Sed failed to match non whitespace characters with character classSed 无法将非空白字符与字符类匹配
【发布时间】:2021-04-05 15:32:10
【问题描述】:

我想提取/etc/lvm/lvm.conf 中配置的过滤规则,例如filter = [ "r|/dev/sda|" ]。我希望sed 返回"r|/dev/sda|"。所以我尝试了以下脚本:

echo ' filter = [ "r|/dev/sda|" ] ' | sed -r 's:^\s*filter\s*=\s*\[\s*([^\s]+)\s*\]:\1:g'

但它不起作用,脚本返回了filter = [ "r|/dev/sda|" ]。 我已经尝试了几个在线正则表达式测试器,该组已正确匹配。

但是,如果我将 [^\s]+ 替换为 .+,它会起作用。

[^\s]+ 不是表示多个非空白字符

有什么想法吗?

【问题讨论】:

  • 这些简写不能在否定括号表达式中使用。 [^[:space:]] 会起作用。
  • 是的!谢谢,谢谢,非常感谢,@WiktorStribiżew
  • 如果你对grep没问题:试试grep -oP 'filter.*\K".*?"' inputfile
  • @PS。 \K 代表什么?
  • 这是perl 的说法,忽略\K 之前的所有内容。 @vesontio

标签: regex linux sed


【解决方案1】:

累加。致regular-expressions.info

一个关键的语法差异是反斜杠不是 POSIX 括号表达式中的元字符。所以在 POSIX 中,正则表达式 [\d] 匹配 \d

所以您需要将[^\s] 替换为[^[:space:]]空格以外的任何字符)。

Example:

echo ' filter = [ "r|/dev/sda|" ] ' | sed -E 's:^\s*filter\s*=\s*\[\s*([^[:space:]]+)\s*\]:\1:g'

输出:"r|/dev/sda|"

【讨论】:

    【解决方案2】:

    如果 grep 解决方案是可以接受的:

    grep -oP 'filter.*\K".*?"' inputfile
    

    【讨论】:

      【解决方案3】:

      [^[:space:]] 相比,您可以在不使用括号[] 的情况下使用\S+ 来更轻松和更短

      \S 表示空白字符

      echo ' filter = [ "r|/dev/sda|" ] ' | sed -r 's:^\s*filter\s*=\s*\[\s*(\S+)\s*\]:\1:g'
      

      https://ideone.com/PxDX1Q

      【讨论】: