我需要询问您有关grep
在 Debian 中的 Bash 脚本中使用命令的问题。
我有包含以下几行的示例文件:
/fruit-/apple.txt
/fruit-/banana.txt
/fruit-/samples
/vegetables-/carrot.txt
/vegetables-/garlic.txt
我想选择包含 word 的所有行fruit-
。
我可以调用命令:
grep -w "fruit-" file.txt
输出将是:
/fruit-/apple.txt
/fruit-/banana.txt
/fruit-/samples
但是当我使用命令时:
grep -w "fruit" file.txt
我也得到与上面相同的输出。但这是错误的。输出应该是 0。因为我没有输入-
模式。
为什么不正确grep
对待呢-
?
答案1
该-w
选项确实告诉grep
只查找fruit
与“单词”匹配的行,这意味着它必须从行的开头开始,或者前面有“非单词”字符,并且在行的末尾结束或后跟“非单词”字符。
但是,根据手册页,“单词”字符grep
是:
单词组成字符是字母、数字和下划线。
这意味着 是-
一个“非单词”字符,并且fruit-
将匹配“单词搜索”,因为fruit
匹配算法将在到达 时停止-
。
现在,您似乎只想选择前两行之间的内容所在的行/
正是 fruit
,相对于包含图案 fruit
。在这些情况下,您必须使匹配更加明确:
- 使用
grep
,您可以说:
这会将模式锚定到行的开头,并且仅接受grep "^/fruit/" file.txt
-
后没有的那些行fruit
。 - 或者,将
awk
集合/
用作字段分隔符:
这将只接受第一个字段为空(即以 a 开头awk -F/ '!$1&&$2=="fruit"' file.txt
/
)且第二个字段恰好为 的行fruit
。
答案2
@AdminBee已经澄清了什么是单词意味着grep
,我将添加如何告诉它在这种情况下使用单词的其他定义。
grep -w word
或多或少地寻找word
前面或后面都没有单词字符的 s。
某些grep
实现可以-P
选择切换到类似 perl 的正则表达式。
perl
有明确的环视四周用于检查某些内容是否匹配之前或之后的运算符。
grep -w word
分别是和的grep -P '(?<!\w)word(?!\w)'
地方(?<!pattern)
(?!pattern)
消极地向后看和先运营商。
如果你想认为这-
是一个单词成分,你可以将其更改为:
grep -P '(?<![\w-])fruit(?![\w-])'
它将匹配foo fruit bar
orfoo/fruit/bar
或foo/fruit
但不匹配,foo/fruit-bar
因为fruit
后面跟着-
.
或者为了任何字符,但/
:
grep -P '(?<![^/])fruit(?![^/])'
或者为了空格分隔的单词:
grep -P '(?<!\S)word(?!\S)'
(其中\S
,与[^\s]
POSIX 类似,[^[:space:]]
是任何未分类为空白的字符)。