【问题标题】:why grep '\s*' is not working, but grep '\S*' works为什么 grep '\s*' 不工作,但 grep '\S*' 工作
【发布时间】:2021-08-03 15:37:44
【问题描述】:

我是 shell 脚本的新手。 我想在文件中显示以空格或非空格开头的行,但grep '\S*' 有效,grep '\s*' 不匹配任何行。 '\s' 看起来很有效 我的 grep 版本是 3.4。我正在使用 WSL Ubuntu。读取的颜色表示匹配。我试过[[:space:]],结果是一样的 任何人都可以帮忙吗?谢谢

test.fa 包括

ctatccagcaccagatagcatcattttactttcaagcctagaaattgcac
 haha
 
   ok
acttgtatataaaccaaccgaagatgaggattgagagttcatcttggtgg

运行结果

【问题讨论】:

  • \s 根本不保证被 POSIX 标准 grep 支持。请改用[[:space:]]。而不是\S,而是使用[^[:space:]]——这样你就不会依赖于特定于操作系统的扩展。
  • 另外,不要将代码显示为屏幕截图。将其复制并粘贴到您的问题中作为文本Why not upload images of code/errors when asking a question?
  • 您说grep '\s*' 不匹配任何内容,但您的第二个输出显示它匹配所有内容。
  • 不清楚你想要什么。你说“我想在文件中显示以空格或非空格开头的行”。因此,如果该行以空格开头,那么您想要显示它。如果它以非空格开头,那么您想要显示它。那不是“任何非空行”吗?
  • @user1934428 @user1934428 不,[:space:] 是一个字符类,在任何 POSIX 工具中意味着 any white space,无论他们使用的是什么 RE 类型。

标签: regex shell grep


【解决方案1】:

* 表示“前面表达式的零次或多次重复”。所以\S* 匹配零个或多个非空格,而\s* 匹配零个或多个空格,并且将^ 放在前面意味着匹配行首的那些(当被比较的字符串是一行时默认情况下为grep)。

所以在你的输入文件中:

Line 1: ctatccagcaccagatagcatcattttactttcaagcctagaaattgcac
Line 2:  haha
Line 3: 
Line 4:   ok
Line 5: acttgtatataaaccaaccgaagatgaggattgagagttcatcttggtgg

^\S* 在每一行匹配以下内容:

line 1: ctatccagcaccagatagcatcattttactttcaagcctagaaattgcac
Line 2: the null string before the leading blank
Line 3: the null string that is the whole line
Line 4: the null string before the leading blanks
Line 5: acttgtatataaaccaaccgaagatgaggattgagagttcatcttggtgg

^\s* 在每一行匹配以下内容:

line 1: the null string before ctatccagcaccagatagcatcattttactttcaagcctagaaattgcac
Line 2: the leading blank
Line 3: the null string that is the whole line
Line 4: the leading blanks
Line 5: the null string before acttgtatataaaccaaccgaagatgaggattgagagttcatcttggtgg

所以两个正则表达式在每一行都匹配一些东西,匹配的颜色是每个匹配字符串中的可打印(即非空和非空白)字符。

要显示以空格开头的行:

grep '^\s'

并显示以非空格开头的行:

grep '^\S'

显示空行是:

grep -v '.'

如果您的 grep 不支持 \s/\S,则使用 [[:space:]]/[^[:space:]] 代替,如果它是 POSIX grep 或任何 grep 中的 [ \t]/[^ \t]

【讨论】:

  • 谢谢,如果没有其他匹配字符串,^\S* 和 ^\s* 可以匹配空字符串吗?
  • @Miracle 正则表达式比较匹配输入中最左边最长的字符串,所以它们并不是真的“如果没有其他匹配的字符串可以匹配空字符串”,只是它们匹配 前面的表达式(\S 或 \s)出现 0 次或多次,因此 0 个匹配项与 1 个或多个匹配项一样有效。
  • @Miracls 试试echo "abc" | grep 'y',当然你不会得到任何输出,因为输入中没有y。现在尝试echo "abc" | grep 'y*',你确实得到了输出,因为y*你要求在输入中找到0个或多个ys,并且在输入中有0个ys。
  • @EdMorton : 要让\s 以这种方式工作,我们不是必须使用-P 来提供此功能吗?
  • @user1934428 \s 正式的 PCRE 功能,但一些实现(实际上,包括 GNU)也将它添加到其他 RE 类型,即使标准没有不需要它。我不知道有任何支持-P 的实现,并且不要\s 添加到非PCRE 实现中(事实上,没有libpcre 编译的GNU grep 将不支持-P,但是仍将支持\s;警告:我不能 100% 确定它是使用 grep 本身提供的还是来自 libc 的正则表达式引擎——在后一种情况下,这可能是特定于操作系统的行为)。
猜你喜欢
  • 2014-12-02
  • 2015-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多