我们想知道通过使用 grep -E 选项来匹配某些变量名称(包括其 $ 前缀)的正确方法。
看来这个 grep macthing 函数只能在没有任何选项或 -e 选项的情况下工作......
>
>
> grep ""'$'status"" /home/ewpadm/.sapenv_wzwms1.csh
if ( $status == 0 ) then
if ( $status == 0 ) then
set rc1 = $status
set rc2 = $status
set rc3 = $status
set rc4 = $status
set rc5 = $status
set rc6 = $status
set rc7 = $status
set rc8 = $status
>
>
> grep -E ""'$'status"" /home/ewpadm/.sapenv_wzwms1.csh
>
>
> grep -E """'$'status"""" /home/ewpadm/.sapenv_wzwms1.csh
>
>
> grep -e ""'$'status"" /home/ewpadm/.sapenv_wzwms1.csh
if ( $status == 0 ) then
if ( $status == 0 ) then
set rc1 = $status
set rc2 = $status
set rc3 = $status
set rc4 = $status
set rc5 = $status
set rc6 = $status
set rc7 = $status
set rc8 = $status
>
>
> grep -e "= "'$'status"" /home/ewpadm/.sapenv_wzwms1.csh
set rc1 = $status
set rc2 = $status
set rc3 = $status
set rc4 = $status
set rc5 = $status
set rc6 = $status
set rc7 = $status
set rc8 = $status
>
>
答案1
$
是 shell 的特殊字符(用于引入一些扩展,例如$param
, $(cmdsubst)
,$((arithmetic))
)和正则表达式(在所有基本的,扩展( -E
,以前egrep
),珀尔( -P
//-X perl
--perl-regexp
),增强的( -X
/ --augmented-regexp
)) 表示在主语末尾匹配,因此您需要对两者进行转义,最好在'...'
for shell 和正则表达式中使用\$
or进行转义(并且在大多数 shell 中也很特殊,也可以用 引起来) :[$]
\
[...]
'...'
在基本 RE(没有-E
/ -P
/ -X
...)中,$
仅在正则表达式末尾或在某些情况下 a 之前是特殊的,因此\)
这里正则表达式可以是$status
,而在其他正则表达式变体(包括扩展正则表达式)中,它通常总是特殊的,因此正则表达式必须是\$status
或[$]status
。
使用(以前的)-F
选项grep
fgrep
固定字符串避免必须进行正则表达式转义。类似 Perl 的正则表达式也可以\Q...\E
用于引用。所以,有很多选择:
grep -F '$status'
grep '$status'
grep '\$status'
grep '[$]status'
grep -E '\$status'
grep -E '[$]status'
非标:
grep -P '\$status'
grep -P '[$]status'
grep -P '\Q$status\E'
grep -X '\$status'
grep -X '[$]status'
在某些 shell 中,\
and"
也可以用作引用运算符,但反斜杠 和$
在 中通常仍然是特殊的"..."
,因此这会使其在这里变得尴尬。'...'
是最强的引号(在某些 shell 中,如rc
和 派生物,是唯一的引号),因此您通常希望在 regexp 周围使用这些引号,其中许多运算符 ( ^$*?\[](){}|
) 在大多数 shell 的语法中也恰好是特殊的。
无论如何,那些也会$status
在里面找到
$status2
,$status_old
或者$statusing
$$status
($$
其次是status
)\$status
$status
或任何引用字面意思的csh
并且不会发现
${status}
${status[1]}
(下标)${status:q}
(修饰语)$#status
或${#status}
(字数)$%status
或${%status}
(字符数)@ status++
/if ( status == 0 ) then
(数学表达式,其中变量(有时)可以在没有$
前缀的情况下使用)。
使用字边界运算符(\b
在 perl 或增强正则表达式中\b
,\>
或[[:>:]]
在 BRE 或 ERE 的某些实现中作为非标准扩展)将有助于解决第一类问题:
grep -P '\$status\b'
没有字边界,可以手动完成:
grep -E '\$status([^_[:alnum:]]|$)'
grep '$status\([^_[:alnum:]].*\)\{0,1\}$'
我们寻找的是$status
后面跟着一个不属于变量名的字符或行尾,或者在没有交替运算符¹的 BRE 中,但如今具有\{0,1\}
与 ERE 等价的字符?
,$status
后面跟着一个非变量成分和任意数量的字符,直到行尾。
解决更多问题:
grep -P '\$\{?[#%]?status\b'
grep -E '\$\{?[#%]?status([^_[:alnum:]]|$)'
grep '${\{0,1\}[#%]\{0,1\}status\([^_[:alnum:]].*\)\{0,1\}$'
1 尽管某些grep
实现将\|
其作为非标准扩展。