这是我的代码,我在 2014 年中期更新到最新版本的 Macbook Pro 上。我使用 Bash 5.1.8
apples-MacBook-Pro:Documents apple$ egrep s* states.txt
apples-MacBook-Pro:Documents apple$ egrep "s*" states.txt
Alabama
Alaska
Arizona
Arkansas
California
Colorado
Connecticut
Delaware
Florida
Georgia
Hawaii
Idaho
Illinois
Indiana
Iowa
Kansas
Kentucky
Louisiana
Maine
Maryland
Massachusetts
Michigan
Minnesota
Mississippi
Missouri
Montana
Nebraska
Nevada
New Hampshire
New Jersey
New Mexico
New York
North Carolina
North Dakota
Ohio
Oklahoma
Oregon
Pennsylvania
Rhode Island
South Carolina
South Dakota
Tennessee
Texas
Utah
Vermont
Virginia
Washington
West Virginia
Wisconsin
Wyoming
apples-MacBook-Pro:Documents apple$ egrep s{2} states.txt
Massachusetts
Mississippi
Missouri
Tennessee
apples-MacBook-Pro:Documents apple$ egrep "s{2}" states.txt
Massachusetts
Mississippi
Missouri
Tennessee
如您所见,如果我不引用 s*,egrep 不会解释元字符 *,(我假设它将 * 视为文字?)但如果我引用 s,则它被视为元字符,正如预期的那样. 但是,使用 {} 的情况并非如此,无论我是否引用了正则表达式,它都被 shell 解释为元字符。
为什么会出现差异?
如果你不引用
s*
, egrep 甚至不会接收元字符*
,因为通配符在命令执行之前由 bash 扩展——这是文件通配符在 Unix shell 中工作的通常方式。由于您有一个与此通配符匹配的文件(完全相同的 states.txt),因此 bash 将运行的实际命令是. (当然,如果有更多以 's' 开头的文件,它们将作为附加参数包含在内。)
egrep states.txt states.txt
只有当通配符不匹配任何文件时,它才会被原封不动地传递给程序(例如
xnughxkrtb*
,可能会保持原样)。您可以通过添加前缀来找出实际的命令echo
——因为通配符扩展是由 shell 完成的,所以对于 echo 和 egrep 来说也是一样的。另一方面,如果您确实引用了
s*
, egrep 会完全按照书面形式收到它。(虽然在 egrep 中它不是通配符,而是正则表达式,它可以匹配所有内容,因为任何字符串都有“零个或多个”'s' 字符,这就是它输出所有状态的原因。)shell 还可以识别
\
抑制特殊字符,因此egrep s\* states.txt
也可以。(如果您希望 egrep 本身从字面上接收反斜杠,您可能需要将其加倍。)这几乎是相同的情况,
{}
是另一种类型的外壳扩展。但是,在您的情况下,它碰巧仍然可以不加引号地工作,因为这种类型的 shell 扩展不会触发,除非它至少有两个逗号分隔的项目(或一个范围)。也就是说,{a,b}
或者{a..z}
由 bash 扩展,但{a}
单独不是。例如,如果您尝试
s{2,5}
不使用引号,则 shell会扩展它,并且生成的命令将是. (同样,您可以通过先使用来检测到这一点。)egrep s2 s5 states.txt
echo