我相信我们大多数人都知道,当我们希望某些正则表达式与行首的字符串匹配时,我们必须使用“^”...
但是,我试图理解“行首为空字符串”的真正含义
我知道 echo "Hello World" | grep ^H 它匹配
因此请查看这些命令的输出:
[sergio@localhost ~]$ dd if=/dev/zero of=/tmp/texto count=1 bs=1 2>/dev/null
[sergio@localhost ~]$ od -ta /tmp/texto
0000000 nul
0000001
到目前为止一切都如预期,因此:
[sergio@localhost ~]$ echo "Hello" >> /tmp/texto
[sergio@localhost ~]$ grep -a "^Hello" /tmp/texto
好吧,我必须承认的第一件事是没想到的,在 Hello 之前有一个空字符,那么为什么它不匹配呢?
好的,让我们以 perl 风格使用 grep:
[sergio@localhost ~]$ grep -a -P "\x00Hello" /tmp/texto
Hello
好的,匹配
但我不明白(也许我有一些误解)为什么 grep -a "^Hello" 不匹配......
你可以帮帮我吗?
提前致谢!
答案1
你混淆了空字符(二进制值 0)与空字符串。
“行首的空字符串”只是不存在的内容在第一个字符之前行末的空字符串同样是行末字符后的非内容。空字符串可以被认为是由“空字符串,空字符串”组成,而包含一些内容的字符串可以被认为是“空字符串,Hello world,空字符串”。
C 中的字符串表示为一系列非 0 字节,后跟一个或多个 0 字节,表示字符串终止,但这与正则表达式中的“空字符串”完全不同,实际上很大程度上是 C 编程语言和标准库中的内部选择。很少有其他语言这样做,但即使如此也可以表示空字符串。
答案2
“空字符串”不同于“空字符”。空字符串是空字符串“”。空字符是所有位都设置为 0 的字符。它可以用双引号表示为 \0,因此 dd 命令的结果为“\0”。然后附加操作将其变为“\0Hello”。这不是空字符串。模式“^Hello”仅匹配以“Hello”开头的行,而您的模式不匹配,因为它以“\0”而不是“H”开头。
答案3
五个字符的假想字符串,后跟两个不同的字符串:
^ _ _ _ _ _ $
^ H e l l o $
^ \0 H e l l $
- 美元符号和脱字符不匹配任何字符,它们匹配字符串的边界。
- null (\0) 是一个真实字符,并且像 abcd 一样占用空间……
因此“^H”不会匹配“\0abcd”(就像“^Z”不会匹配“abcd”一样),因为“\0abcd”以空字符开头,而不是“H”。