首页 > 解决方案 > 使用 grep -E 过滤带有特殊符号的行?

问题描述

文件.txt:

vwive
wbvo$nivw
nowev^VWen
wev$
qnwe^

使用命令过滤其中包含“^”的行

1. grep -E "\^" file.txt

输出

nowev^VWen
qnwe^

使用命令过滤其中包含“$”的行

2. grep -E "\$" file.txt

输出

vwive
wbvo$nivw
nowev^VWen
wev$
qnwe^

命令 1通过删除 '^' 但不是命令 2的特殊含义来提供正确的输出。

为什么两个命令的行为不同

标签: linuxbashshellubuntugrep

解决方案


为什么两个命令的行为不同?

因为该\字符是"引号内的转义字符,并且\$是转义序列之一。bash manual double qoutes的一些部分:

将字符括在双引号 ('"') 中会保留引号内所有字符的字面值,但 '$'、'`'、'\' 以及启用历史扩展时的'!' 除外。[...]
反斜杠仅在后跟以下字符之一时才保留其特殊含义:'$'、'`'、'"'、'\' 或换行符。
在双引号内,删除后面跟有这些字符之一的反斜杠。
没有特殊含义的字符前面的反斜杠保持不变。

字符的“特殊含义”\是逃避的东西:

不带引号的反斜杠 '\' 是 Bash 转义字符。它保留下一个字符的字面值

因为^不是其中之一$ ` " \,则"\^"保留两者\^因此它等于'\^'

因为$是其中之一,则"\$"等于'$'。斜杠 get 被删除并被\$解释为$.

这样的错别字很容易用set -x.

$ ( set -x; grep -E "\$" /dev/null; )
+ grep -E '$' /dev/null
$ ( set -x; grep -E '\$' /dev/null; )
+ grep -E '\$' /dev/null

推荐阅读